<commit_before>package aws

import (
	"fmt"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/elastictranscoder"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSElasticTranscoderPreset_import(t *testing.T) {
	resourceName := "aws_elastictranscoder_preset.bar"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckElasticTranscoderPresetDestroy,
		Steps: []resource.TestStep{
			{
				Config: awsElasticTranscoderPresetConfig,
			},

			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSElasticTranscoderPreset_basic(t *testing.T) {
	preset := &elastictranscoder.Preset{}
	name := "aws_elastictranscoder_preset.bar"

	// make sure the old preset was destroyed on each intermediate step
	// these are very easy to leak
	checkExists := func(replaced bool) resource.TestCheckFunc {
		return func(s *terraform.State) error {
			conn := testAccProvider.Meta().(*AWSClient).elastictranscoderconn

			if replaced {
				_, err := conn.ReadPreset(&elastictranscoder.ReadPresetInput{Id: preset.Id})
				if err != nil {
					return nil
				}

				return fmt.Errorf("Preset Id %v should not exist", *preset.Id)
			}

			rs, ok := s.RootModule().Resources[name]
			if !ok {
				return fmt.Errorf("Not found: %s", name)
			}
			if rs.Primary.ID == "" {
				return fmt.Errorf("No Preset ID is set")
			}

			out, err := conn.ReadPreset(&elastictranscoder.ReadPresetInput{
				Id: aws.String(rs.Primary.ID),
			})

			if err != nil {
				return err
			}

			preset = out.Preset

			return nil

		}
	}

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckElasticTranscoderPresetDestroy,
		Steps: []resource.TestStep{
			{
				Config: awsElasticTranscoderPresetConfig,
				Check: resource.ComposeTestCheckFunc(
					checkExists(false),
				),
			},
			{
				ResourceName:      name,
				ImportState:       true,
				ImportStateVerify: true,
			},
			{
				Config: awsElasticTranscoderPresetConfig2,
				Check: resource.ComposeTestCheckFunc(
					checkExists(true),
				),
			},
			{
				ResourceName:      name,
				ImportState:       true,
				ImportStateVerify: true,
			},
			{
				Config: awsElasticTranscoderPresetConfig3,
				Check: resource.ComposeTestCheckFunc(
					checkExists(true),
				),
			},
			{
				ResourceName:      name,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

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

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

		out, err := conn.ReadPreset(&elastictranscoder.ReadPresetInput{
			Id: aws.String(rs.Primary.ID),
		})

		if err == nil {
			if out.Preset != nil && *out.Preset.Id == rs.Primary.ID {
				return fmt.Errorf("Elastic Transcoder Preset still exists")
			}
		}

		awsErr, ok := err.(awserr.Error)
		if !ok {
			return err
		}

		if awsErr.Code() != "ResourceNotFoundException" {
			return fmt.Errorf("unexpected error: %s", awsErr)
		}

	}
	return nil
}

const awsElasticTranscoderPresetConfig = `
resource "aws_elastictranscoder_preset" "bar" {
  container   = "mp4"
  description = "elastic transcoder preset test 1"
  name        = "aws_elastictranscoder_preset_tf_test_"

  audio {
    audio_packing_mode = "SingleTrack"
    bit_rate           = 320
    channels           = 2
    codec              = "mp3"
    sample_rate        = 44100
  }
}
`

const awsElasticTranscoderPresetConfig2 = `
resource "aws_elastictranscoder_preset" "bar" {
  container   = "mp4"
  description = "elastic transcoder preset test 2"
  name        = "aws_elastictranscoder_preset_tf_test_"

  audio {
    audio_packing_mode = "SingleTrack"
    bit_rate           = 128
    channels           = 2
    codec              = "AAC"
    sample_rate        = 48000
  }

  audio_codec_options {
    profile = "auto"
  }

  video {
    bit_rate             = "auto"
    codec                = "H.264"
    display_aspect_ratio = "16:9"
    fixed_gop            = "true"
    frame_rate           = "auto"
    keyframes_max_dist   = 90
    max_height           = 1080
    max_width            = 1920
    padding_policy       = "Pad"
    sizing_policy        = "Fit"
  }

  video_codec_options {
    Profile            = "main"
    Level              = "4.1"
    MaxReferenceFrames = 4
  }

  thumbnails {
    format         = "jpg"
    interval       = 5
    max_width      = 960
    max_height     = 540
    padding_policy = "Pad"
    sizing_policy  = "Fit"
  }
}
`

const awsElasticTranscoderPresetConfig3 = `
resource "aws_elastictranscoder_preset" "bar" {
  container   = "mp4"
  description = "elastic transcoder preset test 3"
  name        = "aws_elastictranscoder_preset_tf_test_"

  audio {
    audio_packing_mode = "SingleTrack"
    bit_rate           = 96
    channels           = 2
    codec              = "AAC"
    sample_rate        = 44100
  }

  audio_codec_options {
    profile = "AAC-LC"
  }

  video {
    bit_rate             = "1600"
    codec                = "H.264"
    display_aspect_ratio = "16:9"
    fixed_gop            = "false"
    frame_rate           = "auto"
    max_frame_rate       = "60"
    keyframes_max_dist   = 240
    max_height           = "auto"
    max_width            = "auto"
    padding_policy       = "Pad"
    sizing_policy        = "Fit"
  }

  video_codec_options {
    Profile                  = "main"
    Level                    = "2.2"
    MaxReferenceFrames       = 3
    InterlaceMode            = "Progressive"
    ColorSpaceConversionMode = "None"
  }

  video_watermarks {
    id                = "Terraform Test"
    max_width         = "20%"
    max_height        = "20%"
    sizing_policy     = "ShrinkToFit"
    horizontal_align  = "Right"
    horizontal_offset = "10px"
    vertical_align    = "Bottom"
    vertical_offset   = "10px"
    opacity           = "55.5"
    target            = "Content"
  }

  thumbnails {
    format         = "png"
    interval       = 120
    max_width      = "auto"
    max_height     = "auto"
    padding_policy = "Pad"
    sizing_policy  = "Fit"
  }
}
`
<commit_msg>Correct VideoCodecOptions map in example configs<commit_after>package aws

import (
	"fmt"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/elastictranscoder"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSElasticTranscoderPreset_import(t *testing.T) {
	resourceName := "aws_elastictranscoder_preset.bar"

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckElasticTranscoderPresetDestroy,
		Steps: []resource.TestStep{
			{
				Config: awsElasticTranscoderPresetConfig,
			},

			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSElasticTranscoderPreset_basic(t *testing.T) {
	preset := &elastictranscoder.Preset{}
	name := "aws_elastictranscoder_preset.bar"

	// make sure the old preset was destroyed on each intermediate step
	// these are very easy to leak
	checkExists := func(replaced bool) resource.TestCheckFunc {
		return func(s *terraform.State) error {
			conn := testAccProvider.Meta().(*AWSClient).elastictranscoderconn

			if replaced {
				_, err := conn.ReadPreset(&elastictranscoder.ReadPresetInput{Id: preset.Id})
				if err != nil {
					return nil
				}

				return fmt.Errorf("Preset Id %v should not exist", *preset.Id)
			}

			rs, ok := s.RootModule().Resources[name]
			if !ok {
				return fmt.Errorf("Not found: %s", name)
			}
			if rs.Primary.ID == "" {
				return fmt.Errorf("No Preset ID is set")
			}

			out, err := conn.ReadPreset(&elastictranscoder.ReadPresetInput{
				Id: aws.String(rs.Primary.ID),
			})

			if err != nil {
				return err
			}

			preset = out.Preset

			return nil

		}
	}

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckElasticTranscoderPresetDestroy,
		Steps: []resource.TestStep{
			{
				Config: awsElasticTranscoderPresetConfig,
				Check: resource.ComposeTestCheckFunc(
					checkExists(false),
				),
			},
			{
				ResourceName:      name,
				ImportState:       true,
				ImportStateVerify: true,
			},
			{
				Config: awsElasticTranscoderPresetConfig2,
				Check: resource.ComposeTestCheckFunc(
					checkExists(true),
				),
			},
			{
				ResourceName:      name,
				ImportState:       true,
				ImportStateVerify: true,
			},
			{
				Config: awsElasticTranscoderPresetConfig3,
				Check: resource.ComposeTestCheckFunc(
					checkExists(true),
				),
			},
			{
				ResourceName:      name,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

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

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

		out, err := conn.ReadPreset(&elastictranscoder.ReadPresetInput{
			Id: aws.String(rs.Primary.ID),
		})

		if err == nil {
			if out.Preset != nil && *out.Preset.Id == rs.Primary.ID {
				return fmt.Errorf("Elastic Transcoder Preset still exists")
			}
		}

		awsErr, ok := err.(awserr.Error)
		if !ok {
			return err
		}

		if awsErr.Code() != "ResourceNotFoundException" {
			return fmt.Errorf("unexpected error: %s", awsErr)
		}

	}
	return nil
}

const awsElasticTranscoderPresetConfig = `
resource "aws_elastictranscoder_preset" "bar" {
  container   = "mp4"
  description = "elastic transcoder preset test 1"
  name        = "aws_elastictranscoder_preset_tf_test_"

  audio {
    audio_packing_mode = "SingleTrack"
    bit_rate           = 320
    channels           = 2
    codec              = "mp3"
    sample_rate        = 44100
  }
}
`

const awsElasticTranscoderPresetConfig2 = `
resource "aws_elastictranscoder_preset" "bar" {
  container   = "mp4"
  description = "elastic transcoder preset test 2"
  name        = "aws_elastictranscoder_preset_tf_test_"

  audio {
    audio_packing_mode = "SingleTrack"
    bit_rate           = 128
    channels           = 2
    codec              = "AAC"
    sample_rate        = 48000
  }

  audio_codec_options {
    profile = "auto"
  }

  video {
    bit_rate             = "auto"
    codec                = "H.264"
    display_aspect_ratio = "16:9"
    fixed_gop            = "true"
    frame_rate           = "auto"
    keyframes_max_dist   = 90
    max_height           = 1080
    max_width            = 1920
    padding_policy       = "Pad"
    sizing_policy        = "Fit"
  }

  video_codec_options = {
    Profile            = "main"
    Level              = "4.1"
    MaxReferenceFrames = 4
  }

  thumbnails {
    format         = "jpg"
    interval       = 5
    max_width      = 960
    max_height     = 540
    padding_policy = "Pad"
    sizing_policy  = "Fit"
  }
}
`

const awsElasticTranscoderPresetConfig3 = `
resource "aws_elastictranscoder_preset" "bar" {
  container   = "mp4"
  description = "elastic transcoder preset test 3"
  name        = "aws_elastictranscoder_preset_tf_test_"

  audio {
    audio_packing_mode = "SingleTrack"
    bit_rate           = 96
    channels           = 2
    codec              = "AAC"
    sample_rate        = 44100
  }

  audio_codec_options {
    profile = "AAC-LC"
  }

  video {
    bit_rate             = "1600"
    codec                = "H.264"
    display_aspect_ratio = "16:9"
    fixed_gop            = "false"
    frame_rate           = "auto"
    max_frame_rate       = "60"
    keyframes_max_dist   = 240
    max_height           = "auto"
    max_width            = "auto"
    padding_policy       = "Pad"
    sizing_policy        = "Fit"
  }

  video_codec_options = {
    Profile                  = "main"
    Level                    = "2.2"
    MaxReferenceFrames       = 3
    InterlaceMode            = "Progressive"
    ColorSpaceConversionMode = "None"
  }

  video_watermarks {
    id                = "Terraform Test"
    max_width         = "20%"
    max_height        = "20%"
    sizing_policy     = "ShrinkToFit"
    horizontal_align  = "Right"
    horizontal_offset = "10px"
    vertical_align    = "Bottom"
    vertical_offset   = "10px"
    opacity           = "55.5"
    target            = "Content"
  }

  thumbnails {
    format         = "png"
    interval       = 120
    max_width      = "auto"
    max_height     = "auto"
    padding_policy = "Pad"
    sizing_policy  = "Fit"
  }
}
`
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"

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

func resourceAwsVpcPeeringConnectionOptions() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsVpcPeeringConnectionOptionsCreate,
		Read:   resourceAwsVpcPeeringConnectionOptionsRead,
		Update: resourceAwsVpcPeeringConnectionOptionsUpdate,
		Delete: resourceAwsVpcPeeringConnectionOptionsDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"vpc_peering_connection_id": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"accepter":  vpcPeeringConnectionOptionsSchema(),
			"requester": vpcPeeringConnectionOptionsSchema(),
		},
	}
}

func resourceAwsVpcPeeringConnectionOptionsCreate(d *schema.ResourceData, meta interface{}) error {
	d.SetId(d.Get("vpc_peering_connection_id").(string))
	return resourceAwsVpcPeeringConnectionOptionsUpdate(d, meta)
}

func resourceAwsVpcPeeringConnectionOptionsRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn

	pcRaw, _, err := vpcPeeringConnectionRefreshState(conn, d.Id())()
	if err != nil {
		return fmt.Errorf("Error reading VPC Peering Connection: %s", err.Error())
	}

	if pcRaw == nil {
		log.Printf("[WARN] VPC Peering Connection (%s) not found, removing from state", d.Id())
		d.SetId("")
		return nil
	}

	pc := pcRaw.(*ec2.VpcPeeringConnection)

	d.Set("vpc_peering_connection_id", aws.StringValue(pc.VpcPeeringConnectionId))

	if pc.AccepterVpcInfo.PeeringOptions != nil {
		err := d.Set("accepter", flattenVpcPeeringConnectionOptions(pc.AccepterVpcInfo.PeeringOptions))
		if err != nil {
			return fmt.Errorf("Error setting VPC Peering Connection Options accepter information: %s", err.Error())
		}
	}

	if pc.RequesterVpcInfo.PeeringOptions != nil {
		err := d.Set("requester", flattenVpcPeeringConnectionOptions(pc.RequesterVpcInfo.PeeringOptions))
		if err != nil {
			return fmt.Errorf("Error setting VPC Peering Connection Options requester information: %s", err.Error())
		}
	}

	return nil
}

func resourceAwsVpcPeeringConnectionOptionsUpdate(d *schema.ResourceData, meta interface{}) error {
	if err := resourceAwsVpcPeeringConnectionModifyOptions(d, meta); err != nil {
		return fmt.Errorf("Error modifying VPC Peering Connection Options: %s", err.Error())
	}

	return resourceAwsVpcPeeringConnectionOptionsRead(d, meta)
}

func resourceAwsVpcPeeringConnectionOptionsDelete(d *schema.ResourceData, meta interface{}) error {
	// Don't do anything with the underlying VPC peering connection.
	return nil
}
<commit_msg>Remove unnecessary call to 'aws.StringValue()'.<commit_after>package aws

import (
	"fmt"
	"log"

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

func resourceAwsVpcPeeringConnectionOptions() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsVpcPeeringConnectionOptionsCreate,
		Read:   resourceAwsVpcPeeringConnectionOptionsRead,
		Update: resourceAwsVpcPeeringConnectionOptionsUpdate,
		Delete: resourceAwsVpcPeeringConnectionOptionsDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"vpc_peering_connection_id": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"accepter":  vpcPeeringConnectionOptionsSchema(),
			"requester": vpcPeeringConnectionOptionsSchema(),
		},
	}
}

func resourceAwsVpcPeeringConnectionOptionsCreate(d *schema.ResourceData, meta interface{}) error {
	d.SetId(d.Get("vpc_peering_connection_id").(string))
	return resourceAwsVpcPeeringConnectionOptionsUpdate(d, meta)
}

func resourceAwsVpcPeeringConnectionOptionsRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn

	pcRaw, _, err := vpcPeeringConnectionRefreshState(conn, d.Id())()
	if err != nil {
		return fmt.Errorf("Error reading VPC Peering Connection: %s", err.Error())
	}

	if pcRaw == nil {
		log.Printf("[WARN] VPC Peering Connection (%s) not found, removing from state", d.Id())
		d.SetId("")
		return nil
	}

	pc := pcRaw.(*ec2.VpcPeeringConnection)

	d.Set("vpc_peering_connection_id", pc.VpcPeeringConnectionId)

	if pc.AccepterVpcInfo.PeeringOptions != nil {
		err := d.Set("accepter", flattenVpcPeeringConnectionOptions(pc.AccepterVpcInfo.PeeringOptions))
		if err != nil {
			return fmt.Errorf("Error setting VPC Peering Connection Options accepter information: %s", err.Error())
		}
	}

	if pc.RequesterVpcInfo.PeeringOptions != nil {
		err := d.Set("requester", flattenVpcPeeringConnectionOptions(pc.RequesterVpcInfo.PeeringOptions))
		if err != nil {
			return fmt.Errorf("Error setting VPC Peering Connection Options requester information: %s", err.Error())
		}
	}

	return nil
}

func resourceAwsVpcPeeringConnectionOptionsUpdate(d *schema.ResourceData, meta interface{}) error {
	if err := resourceAwsVpcPeeringConnectionModifyOptions(d, meta); err != nil {
		return fmt.Errorf("Error modifying VPC Peering Connection Options: %s", err.Error())
	}

	return resourceAwsVpcPeeringConnectionOptionsRead(d, meta)
}

func resourceAwsVpcPeeringConnectionOptionsDelete(d *schema.ResourceData, meta interface{}) error {
	// Don't do anything with the underlying VPC peering connection.
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math/rand"
	"strings"
)

func main() {
	const distance = 57600000
	spaceline := ""
	trip := ""

	fmt.Printf("%-18v %4v %v %7v\n", "Spaceline", "Days", "Round-trip", "Price")
	fmt.Println("===============================================")
	for count :=0; count < 10; count++ {

		speed := rand.Intn(16) + 15
		days := (distance / speed) / 86164
		price := days / 2

		switch rand.Intn(3) {
		case 0:
			spaceline = "Space Adventures"
		case 1:
			spaceline = "SpaceX"
		case 2:
			spaceline = "Virgin Galactic"
		}

		switch rand.Intn(2) {
		case 0:
			trip = "One Way"
		case 1:
			trip = "Round Trip"
		}

		if strings.Contains(trip, "Round") {
			price = price * 2
			days = days * 2
		}

		fmt.Printf("%-18v %4v %-10v $%4v\n", spaceline, days, trip, price)
	}
}
<commit_msg>Cleaned up the formatting, and added a comment.<commit_after>package main

import (
	"fmt"
	"math/rand"
	"strings"
)

func main() {
	const distance = 57600000
	spaceline := ""
	trip := ""

	fmt.Printf("%-18v %4v %v %7v\n", "Spaceline", "Days", "Round-trip", "Price")
	fmt.Println("==========================================")
	for count :=0; count < 10; count++ {

		speed := rand.Intn(16) + 15
		days := (distance / speed) / 86164
		price := days / 2

		switch rand.Intn(3) {
		case 0:
			spaceline = "Space Adventures"
		case 1:
			spaceline = "SpaceX"
		case 2:
			spaceline = "Virgin Galactic"
		}

		switch rand.Intn(2) {
		case 0:
			trip = "One Way"
		case 1:
			trip = "Round Trip"
		}

		/*
		The assignment actually called for having the days listed for just a
		one-way trip. I did that, and then decided to change it so that the
		listed days would show the total, round trip time, assuming the return
		distance and rate were the same.
		*/
		if strings.Contains(trip, "Round") {
			price = price * 2
			days = days * 2
		}

		fmt.Printf("%-18v %4v %-12v $%4v\n", spaceline, days, trip, price)
	}
}
<|endoftext|>


<commit_before>package acceptance_test

import (
	"fmt"
	"io/ioutil"
	"os/exec"
	"regexp"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/rds"
	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/generator"
	"github.com/cloudfoundry-incubator/cf-test-helpers/helpers"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

const (
	DB_CREATE_TIMEOUT = 30 * time.Minute
)

var _ = Describe("RDS broker", func() {
	const (
		serviceName  = "postgres"
		testPlanName = "M-dedicated-9.5"
		region       = "eu-west-1"
	)

	It("should have registered the postgres service", func() {
		plans := cf.Cf("marketplace").Wait(DEFAULT_TIMEOUT)
		Expect(plans).To(Exit(0))
		Expect(plans).To(Say(serviceName))
	})

	It("has the expected plans available", func() {
		plans := cf.Cf("marketplace", "-s", serviceName).Wait(DEFAULT_TIMEOUT)
		Expect(plans).To(Exit(0))
		Expect(plans.Out.Contents()).To(ContainSubstring("Free"))
		Expect(plans.Out.Contents()).To(ContainSubstring("S-dedicated-9.5"))
		Expect(plans.Out.Contents()).To(ContainSubstring("S-HA-dedicated-9.5"))
		Expect(plans.Out.Contents()).To(ContainSubstring("M-dedicated-9.5"))
		Expect(plans.Out.Contents()).To(ContainSubstring("M-HA-dedicated-9.5"))
		Expect(plans.Out.Contents()).To(ContainSubstring("L-dedicated-9.5"))
		Expect(plans.Out.Contents()).To(ContainSubstring("L-HA-dedicated-9.5"))
	})

	Context("creating a database instance with default settings", func() {
		// Avoid creating additional tests in this block because this setup and teardown is
		// slow (several minutes).

		var (
			appName         string
			dbInstanceName  string
			rdsInstanceName string
		)
		BeforeEach(func() {
			appName = generator.PrefixedRandomName("CATS-APP-")
			dbInstanceName = generator.PrefixedRandomName("test-db-")
			Expect(cf.Cf("create-service", serviceName, testPlanName, dbInstanceName).Wait(DEFAULT_TIMEOUT)).To(Exit(0))

			pollForRDSCreationCompletion(dbInstanceName)

			rdsInstanceName = getRDSInstanceName(dbInstanceName)
			fmt.Fprintf(GinkgoWriter, "Created RDS instance: %s\n", rdsInstanceName)

			Expect(cf.Cf(
				"push", appName,
				"--no-start",
				"-b", config.GoBuildpackName,
				"-p", "../../example-apps/healthcheck",
				"-f", "../../example-apps/healthcheck/manifest.yml",
				"-d", config.AppsDomain,
			).Wait(CF_PUSH_TIMEOUT)).To(Exit(0))

			Expect(cf.Cf("bind-service", appName, dbInstanceName).Wait(DEFAULT_TIMEOUT)).To(Exit(0))

			Expect(cf.Cf("start", appName).Wait(CF_PUSH_TIMEOUT)).To(Exit(0))
		})

		AfterEach(func() {
			cf.Cf("delete", appName, "-f").Wait(DEFAULT_TIMEOUT)

			Expect(cf.Cf("delete-service", dbInstanceName, "-f").Wait(DEFAULT_TIMEOUT)).To(Exit(0))

			// Poll until destruction is complete, otherwise the org cleanup fails.
			pollForRDSDeletionCompletion(dbInstanceName)

			rdsClient, err := NewRDSClient(region)
			Expect(err).NotTo(HaveOccurred())
			snapshots, err := rdsClient.GetDBFinalSnapshots(rdsInstanceName)
			fmt.Fprintf(GinkgoWriter, "Final snapshots for %s:\n", rdsInstanceName)
			fmt.Fprint(GinkgoWriter, snapshots)
			Expect(err).NotTo(HaveOccurred())
			Expect(snapshots).Should(ContainSubstring(rdsInstanceName))

			snapshotDeletionOutput, err := rdsClient.deleteDBFinalSnapshot(rdsInstanceName)
			fmt.Fprintf(GinkgoWriter, "Snapshot deletion output for %s:\n", rdsInstanceName)
			fmt.Fprint(GinkgoWriter, snapshotDeletionOutput)
			Expect(err).NotTo(HaveOccurred())
		})

		It("can connect to the DB instance from the app", func() {
			By("Sending request to DB Healthcheck app")
			resp, err := httpClient.Get(helpers.AppUri(appName, "/db"))
			Expect(err).NotTo(HaveOccurred())
			body, err := ioutil.ReadAll(resp.Body)
			Expect(err).NotTo(HaveOccurred())
			Expect(resp.StatusCode).To(Equal(200), "Got %d response from healthcheck app. Response body:\n%s\n", resp.StatusCode, string(body))

			By("Sending request to DB Healthcheck app without TLS")
			resp, err = httpClient.Get(helpers.AppUri(appName, "/db?ssl=false"))
			Expect(err).NotTo(HaveOccurred())
			body, err = ioutil.ReadAll(resp.Body)
			Expect(err).NotTo(HaveOccurred())
			Expect(resp.StatusCode).NotTo(Equal(200), "Got %d response from healthcheck app. Response body:\n%s\n", resp.StatusCode, string(body))
			Expect(body).To(MatchRegexp("no pg_hba.conf entry for .* SSL off"), "Connection without TLS did not report a TLS error")

			By("Testing permissions after unbind and rebind")
			resp, err = httpClient.Get(helpers.AppUri(appName, "/db/permissions-check?phase=setup"))
			Expect(err).NotTo(HaveOccurred())
			body, err = ioutil.ReadAll(resp.Body)
			Expect(err).NotTo(HaveOccurred())
			Expect(resp.StatusCode).To(Equal(200), "Got %d response setting up multi-user test table. Response body:\n%s\n", resp.StatusCode, string(body))

			Expect(cf.Cf("stop", appName).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
			Expect(cf.Cf("unbind-service", appName, dbInstanceName).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
			Expect(cf.Cf("bind-service", appName, dbInstanceName).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
			Expect(cf.Cf("start", appName).Wait(DEFAULT_TIMEOUT)).To(Exit(0))

			resp, err = httpClient.Get(helpers.AppUri(appName, "/db/permissions-check?phase=test"))
			Expect(err).NotTo(HaveOccurred())
			body, err = ioutil.ReadAll(resp.Body)
			Expect(err).NotTo(HaveOccurred())
			Expect(resp.StatusCode).To(Equal(200), "Got %d response testing multi-user permissions. Response body:\n%s\n", resp.StatusCode, string(body))
		})
	})

	Context("creating a database instance with custom parameters", func() {

		var (
			dbInstanceName  string
			rdsInstanceName string
		)

		BeforeEach(func() {
			dbInstanceName = generator.PrefixedRandomName("test-db-")
			Expect(cf.Cf("create-service", serviceName, testPlanName, dbInstanceName, "-c", `{"skip_final_snapshot": "true"}`).Wait(DEFAULT_TIMEOUT)).To(Exit(0))

			pollForRDSCreationCompletion(dbInstanceName)

			rdsInstanceName = getRDSInstanceName(dbInstanceName)
			fmt.Fprintf(GinkgoWriter, "Created RDS instance: %s\n", rdsInstanceName)
		})

		It("should not create a final snapshot when `skip_final_snapshot` is set to true", func() {
			Expect(cf.Cf("delete-service", dbInstanceName, "-f").Wait(DEFAULT_TIMEOUT)).To(Exit(0))

			// Poll until destruction is complete, otherwise the org cleanup fails.
			pollForRDSDeletionCompletion(dbInstanceName)

			rdsClient, err := NewRDSClient(region)
			Expect(err).NotTo(HaveOccurred())
			snapshots, err := rdsClient.GetDBFinalSnapshots(rdsInstanceName)
			fmt.Fprintf(GinkgoWriter, "Final snapshots for %s:\n", rdsInstanceName)
			fmt.Fprint(GinkgoWriter, snapshots)
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).Should(ContainSubstring("DBSnapshotNotFound"))

			snapshotDeletionOutput, err := rdsClient.deleteDBFinalSnapshot(rdsInstanceName)
			fmt.Fprintf(GinkgoWriter, "Snapshot deletion output for %s:\n", rdsInstanceName)
			fmt.Fprint(GinkgoWriter, snapshotDeletionOutput)
			Expect(err).To(HaveOccurred())
		})

		It("should create a final snapshot if we set `skip_final_snapshot` back to false", func() {
			Expect(cf.Cf("update-service", dbInstanceName, "-c", `{"skip_final_snapshot": "false"}`).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
			pollForRDSUpdateCompletion(dbInstanceName)
			Expect(cf.Cf("delete-service", dbInstanceName, "-f").Wait(DEFAULT_TIMEOUT)).To(Exit(0))

			// Poll until destruction is complete, otherwise the org cleanup fails.
			pollForRDSDeletionCompletion(dbInstanceName)

			rdsClient, err := NewRDSClient(region)
			Expect(err).NotTo(HaveOccurred())
			snapshots, err := rdsClient.GetDBFinalSnapshots(rdsInstanceName)
			fmt.Fprintf(GinkgoWriter, "Final snapshots for %s:\n", rdsInstanceName)
			fmt.Fprint(GinkgoWriter, snapshots)
			Expect(err).NotTo(HaveOccurred())
			Expect(snapshots).Should(ContainSubstring(rdsInstanceName))

			snapshotDeletionOutput, err := rdsClient.deleteDBFinalSnapshot(rdsInstanceName)
			fmt.Fprintf(GinkgoWriter, "Snapshot deletion output for %s:\n", rdsInstanceName)
			fmt.Fprint(GinkgoWriter, snapshotDeletionOutput)
			Expect(err).NotTo(HaveOccurred())
		})
	})
})

func pollForRDSCreationCompletion(dbInstanceName string) {
	fmt.Fprint(GinkgoWriter, "Polling for RDS creation to complete")
	Eventually(func() *Buffer {
		fmt.Fprint(GinkgoWriter, ".")
		command := quietCf("cf", "service", dbInstanceName).Wait(DEFAULT_TIMEOUT)
		Expect(command).To(Exit(0))
		return command.Out
	}, DB_CREATE_TIMEOUT, 15*time.Second).Should(Say("create succeeded"))
	fmt.Fprint(GinkgoWriter, "done\n")
}

func pollForRDSDeletionCompletion(dbInstanceName string) {
	fmt.Fprint(GinkgoWriter, "Polling for RDS destruction to complete")
	Eventually(func() *Buffer {
		fmt.Fprint(GinkgoWriter, ".")
		command := quietCf("cf", "services").Wait(DEFAULT_TIMEOUT)
		Expect(command).To(Exit(0))
		return command.Out
	}, DB_CREATE_TIMEOUT, 15*time.Second).ShouldNot(Say(dbInstanceName))
	fmt.Fprint(GinkgoWriter, "done\n")
}

func pollForRDSUpdateCompletion(dbInstanceName string) {
	fmt.Fprint(GinkgoWriter, "Polling for RDS update to complete")
	Eventually(func() *Buffer {
		fmt.Fprint(GinkgoWriter, ".")
		command := quietCf("cf", "service", dbInstanceName).Wait(DEFAULT_TIMEOUT)
		Expect(command).To(Exit(0))
		return command.Out
	}, DB_CREATE_TIMEOUT, 15*time.Second).Should(Say("update succeeded"))
	fmt.Fprint(GinkgoWriter, "done\n")
}

func getRDSInstanceName(dbInstanceName string) string {
	serviceOutput := cf.Cf("service", dbInstanceName).Wait(DEFAULT_TIMEOUT)
	Expect(serviceOutput).To(Exit(0))
	rxp, _ := regexp.Compile("rdsbroker-([a-z0-9-]+)")
	return string(rxp.Find(serviceOutput.Out.Contents()))
}

// quietCf is an equivelent of cf.Cf that doesn't send the output to
// GinkgoWriter. Used when you don't want the output, even in verbose mode (eg
// when polling the API)
func quietCf(program string, args ...string) *Session {
	command, err := Start(exec.Command(program, args...), nil, nil)
	Expect(err).NotTo(HaveOccurred())
	return command
}

type RDSClient struct {
	region string
	rdssvc *rds.RDS
}

func NewRDSClient(region string) (*RDSClient, error) {
	sess, err := session.NewSession(&aws.Config{Region: aws.String(region)})
	if err != nil {
		fmt.Println("Failed to create AWS session,", err)
		return nil, err
	}

	rdssvc := rds.New(sess)
	return &RDSClient{
		region: region,
		rdssvc: rdssvc,
	}, nil
}

func (r *RDSClient) GetDBFinalSnapshots(ID string) (*rds.DescribeDBSnapshotsOutput, error) {
	params := &rds.DescribeDBSnapshotsInput{
		DBSnapshotIdentifier: aws.String(ID + "-final-snapshot"),
	}

	resp, err := r.rdssvc.DescribeDBSnapshots(params)

	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (r *RDSClient) deleteDBFinalSnapshot(ID string) (*rds.DeleteDBSnapshotOutput, error) {
	params := &rds.DeleteDBSnapshotInput{
		DBSnapshotIdentifier: aws.String(ID + "-final-snapshot"),
	}

	resp, err := r.rdssvc.DeleteDBSnapshot(params)

	if err != nil {
		return nil, err
	}
	return resp, nil
}
<commit_msg>Use the 'Free' RDS plan for the tests where possible.<commit_after>package acceptance_test

import (
	"fmt"
	"io/ioutil"
	"os/exec"
	"regexp"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/rds"
	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/generator"
	"github.com/cloudfoundry-incubator/cf-test-helpers/helpers"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

const (
	DB_CREATE_TIMEOUT = 30 * time.Minute
)

var _ = Describe("RDS broker", func() {
	const (
		serviceName              = "postgres"
		testPlanName             = "Free"
		testPlanNameWithSnapshot = "S-dedicated-9.5"
		region                   = "eu-west-1"
	)

	It("should have registered the postgres service", func() {
		plans := cf.Cf("marketplace").Wait(DEFAULT_TIMEOUT)
		Expect(plans).To(Exit(0))
		Expect(plans).To(Say(serviceName))
	})

	It("has the expected plans available", func() {
		plans := cf.Cf("marketplace", "-s", serviceName).Wait(DEFAULT_TIMEOUT)
		Expect(plans).To(Exit(0))
		Expect(plans.Out.Contents()).To(ContainSubstring("Free"))
		Expect(plans.Out.Contents()).To(ContainSubstring("S-dedicated-9.5"))
		Expect(plans.Out.Contents()).To(ContainSubstring("S-HA-dedicated-9.5"))
		Expect(plans.Out.Contents()).To(ContainSubstring("M-dedicated-9.5"))
		Expect(plans.Out.Contents()).To(ContainSubstring("M-HA-dedicated-9.5"))
		Expect(plans.Out.Contents()).To(ContainSubstring("L-dedicated-9.5"))
		Expect(plans.Out.Contents()).To(ContainSubstring("L-HA-dedicated-9.5"))
	})

	Context("creating a database instance", func() {
		// Avoid creating additional tests in this block because this setup and teardown is
		// slow (several minutes).

		var (
			appName         string
			dbInstanceName  string
			rdsInstanceName string
		)
		BeforeEach(func() {
			appName = generator.PrefixedRandomName("CATS-APP-")
			dbInstanceName = generator.PrefixedRandomName("test-db-")
			Expect(cf.Cf("create-service", serviceName, testPlanName, dbInstanceName).Wait(DEFAULT_TIMEOUT)).To(Exit(0))

			pollForRDSCreationCompletion(dbInstanceName)

			rdsInstanceName = getRDSInstanceName(dbInstanceName)
			fmt.Fprintf(GinkgoWriter, "Created RDS instance: %s\n", rdsInstanceName)

			Expect(cf.Cf(
				"push", appName,
				"--no-start",
				"-b", config.GoBuildpackName,
				"-p", "../../example-apps/healthcheck",
				"-f", "../../example-apps/healthcheck/manifest.yml",
				"-d", config.AppsDomain,
			).Wait(CF_PUSH_TIMEOUT)).To(Exit(0))

			Expect(cf.Cf("bind-service", appName, dbInstanceName).Wait(DEFAULT_TIMEOUT)).To(Exit(0))

			Expect(cf.Cf("start", appName).Wait(CF_PUSH_TIMEOUT)).To(Exit(0))
		})

		AfterEach(func() {
			cf.Cf("delete", appName, "-f").Wait(DEFAULT_TIMEOUT)

			Expect(cf.Cf("delete-service", dbInstanceName, "-f").Wait(DEFAULT_TIMEOUT)).To(Exit(0))

			// Poll until destruction is complete, otherwise the org cleanup (in AfterSuite) fails.
			pollForRDSDeletionCompletion(dbInstanceName)
		})

		It("can connect to the DB instance from the app", func() {
			By("Sending request to DB Healthcheck app")
			resp, err := httpClient.Get(helpers.AppUri(appName, "/db"))
			Expect(err).NotTo(HaveOccurred())
			body, err := ioutil.ReadAll(resp.Body)
			Expect(err).NotTo(HaveOccurred())
			Expect(resp.StatusCode).To(Equal(200), "Got %d response from healthcheck app. Response body:\n%s\n", resp.StatusCode, string(body))

			By("Sending request to DB Healthcheck app without TLS")
			resp, err = httpClient.Get(helpers.AppUri(appName, "/db?ssl=false"))
			Expect(err).NotTo(HaveOccurred())
			body, err = ioutil.ReadAll(resp.Body)
			Expect(err).NotTo(HaveOccurred())
			Expect(resp.StatusCode).NotTo(Equal(200), "Got %d response from healthcheck app. Response body:\n%s\n", resp.StatusCode, string(body))
			Expect(body).To(MatchRegexp("no pg_hba.conf entry for .* SSL off"), "Connection without TLS did not report a TLS error")

			By("Testing permissions after unbind and rebind")
			resp, err = httpClient.Get(helpers.AppUri(appName, "/db/permissions-check?phase=setup"))
			Expect(err).NotTo(HaveOccurred())
			body, err = ioutil.ReadAll(resp.Body)
			Expect(err).NotTo(HaveOccurred())
			Expect(resp.StatusCode).To(Equal(200), "Got %d response setting up multi-user test table. Response body:\n%s\n", resp.StatusCode, string(body))

			Expect(cf.Cf("stop", appName).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
			Expect(cf.Cf("unbind-service", appName, dbInstanceName).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
			Expect(cf.Cf("bind-service", appName, dbInstanceName).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
			Expect(cf.Cf("start", appName).Wait(DEFAULT_TIMEOUT)).To(Exit(0))

			resp, err = httpClient.Get(helpers.AppUri(appName, "/db/permissions-check?phase=test"))
			Expect(err).NotTo(HaveOccurred())
			body, err = ioutil.ReadAll(resp.Body)
			Expect(err).NotTo(HaveOccurred())
			Expect(resp.StatusCode).To(Equal(200), "Got %d response testing multi-user permissions. Response body:\n%s\n", resp.StatusCode, string(body))
		})
	})

	Context("final snapshots", func() {

		var (
			dbInstanceName  string
			rdsInstanceName string
		)

		BeforeEach(func() {
			dbInstanceName = generator.PrefixedRandomName("test-db-")
			Expect(cf.Cf("create-service", serviceName, testPlanNameWithSnapshot, dbInstanceName).Wait(DEFAULT_TIMEOUT)).To(Exit(0))

			pollForRDSCreationCompletion(dbInstanceName)

			rdsInstanceName = getRDSInstanceName(dbInstanceName)
			fmt.Fprintf(GinkgoWriter, "Created RDS instance: %s\n", rdsInstanceName)
		})

		It("should create a final snapshot by default", func() {
			Expect(cf.Cf("delete-service", dbInstanceName, "-f").Wait(DEFAULT_TIMEOUT)).To(Exit(0))

			// Poll until destruction is complete, and the snapshot will therefore have been created.
			pollForRDSDeletionCompletion(dbInstanceName)

			rdsClient, err := NewRDSClient(region)
			Expect(err).NotTo(HaveOccurred())
			snapshots, err := rdsClient.GetDBFinalSnapshots(rdsInstanceName)
			fmt.Fprintf(GinkgoWriter, "Final snapshots for %s:\n", rdsInstanceName)
			fmt.Fprint(GinkgoWriter, snapshots)
			Expect(err).NotTo(HaveOccurred())
			Expect(snapshots).Should(ContainSubstring(rdsInstanceName))

			snapshotDeletionOutput, err := rdsClient.deleteDBFinalSnapshot(rdsInstanceName)
			fmt.Fprintf(GinkgoWriter, "Snapshot deletion output for %s:\n", rdsInstanceName)
			fmt.Fprint(GinkgoWriter, snapshotDeletionOutput)
			Expect(err).NotTo(HaveOccurred())
		})

		It("should not create a final snapshot when `skip_final_snapshot` is set to true", func() {
			Expect(cf.Cf("update-service", dbInstanceName, "-c", `{"skip_final_snapshot": "true"}`).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
			pollForRDSUpdateCompletion(dbInstanceName)
			Expect(cf.Cf("delete-service", dbInstanceName, "-f").Wait(DEFAULT_TIMEOUT)).To(Exit(0))

			// Poll until destruction is complete, and the snapshot would therefore have been created.
			pollForRDSDeletionCompletion(dbInstanceName)

			rdsClient, err := NewRDSClient(region)
			Expect(err).NotTo(HaveOccurred())
			snapshots, err := rdsClient.GetDBFinalSnapshots(rdsInstanceName)
			fmt.Fprintf(GinkgoWriter, "Final snapshots for %s:\n", rdsInstanceName)
			fmt.Fprint(GinkgoWriter, snapshots)
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).Should(ContainSubstring("DBSnapshotNotFound"))

			snapshotDeletionOutput, err := rdsClient.deleteDBFinalSnapshot(rdsInstanceName)
			fmt.Fprintf(GinkgoWriter, "Snapshot deletion output for %s:\n", rdsInstanceName)
			fmt.Fprint(GinkgoWriter, snapshotDeletionOutput)
			Expect(err).To(HaveOccurred())
		})

	})
})

func pollForRDSCreationCompletion(dbInstanceName string) {
	fmt.Fprint(GinkgoWriter, "Polling for RDS creation to complete")
	Eventually(func() *Buffer {
		fmt.Fprint(GinkgoWriter, ".")
		command := quietCf("cf", "service", dbInstanceName).Wait(DEFAULT_TIMEOUT)
		Expect(command).To(Exit(0))
		return command.Out
	}, DB_CREATE_TIMEOUT, 15*time.Second).Should(Say("create succeeded"))
	fmt.Fprint(GinkgoWriter, "done\n")
}

func pollForRDSDeletionCompletion(dbInstanceName string) {
	fmt.Fprint(GinkgoWriter, "Polling for RDS destruction to complete")
	Eventually(func() *Buffer {
		fmt.Fprint(GinkgoWriter, ".")
		command := quietCf("cf", "services").Wait(DEFAULT_TIMEOUT)
		Expect(command).To(Exit(0))
		return command.Out
	}, DB_CREATE_TIMEOUT, 15*time.Second).ShouldNot(Say(dbInstanceName))
	fmt.Fprint(GinkgoWriter, "done\n")
}

func pollForRDSUpdateCompletion(dbInstanceName string) {
	fmt.Fprint(GinkgoWriter, "Polling for RDS update to complete")
	Eventually(func() *Buffer {
		fmt.Fprint(GinkgoWriter, ".")
		command := quietCf("cf", "service", dbInstanceName).Wait(DEFAULT_TIMEOUT)
		Expect(command).To(Exit(0))
		return command.Out
	}, DB_CREATE_TIMEOUT, 15*time.Second).Should(Say("update succeeded"))
	fmt.Fprint(GinkgoWriter, "done\n")
}

func getRDSInstanceName(dbInstanceName string) string {
	serviceOutput := cf.Cf("service", dbInstanceName).Wait(DEFAULT_TIMEOUT)
	Expect(serviceOutput).To(Exit(0))
	rxp, _ := regexp.Compile("rdsbroker-([a-z0-9-]+)")
	return string(rxp.Find(serviceOutput.Out.Contents()))
}

// quietCf is an equivelent of cf.Cf that doesn't send the output to
// GinkgoWriter. Used when you don't want the output, even in verbose mode (eg
// when polling the API)
func quietCf(program string, args ...string) *Session {
	command, err := Start(exec.Command(program, args...), nil, nil)
	Expect(err).NotTo(HaveOccurred())
	return command
}

type RDSClient struct {
	region string
	rdssvc *rds.RDS
}

func NewRDSClient(region string) (*RDSClient, error) {
	sess, err := session.NewSession(&aws.Config{Region: aws.String(region)})
	if err != nil {
		fmt.Println("Failed to create AWS session,", err)
		return nil, err
	}

	rdssvc := rds.New(sess)
	return &RDSClient{
		region: region,
		rdssvc: rdssvc,
	}, nil
}

func (r *RDSClient) GetDBFinalSnapshots(ID string) (*rds.DescribeDBSnapshotsOutput, error) {
	params := &rds.DescribeDBSnapshotsInput{
		DBSnapshotIdentifier: aws.String(ID + "-final-snapshot"),
	}

	resp, err := r.rdssvc.DescribeDBSnapshots(params)

	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (r *RDSClient) deleteDBFinalSnapshot(ID string) (*rds.DeleteDBSnapshotOutput, error) {
	params := &rds.DeleteDBSnapshotInput{
		DBSnapshotIdentifier: aws.String(ID + "-final-snapshot"),
	}

	resp, err := r.rdssvc.DeleteDBSnapshot(params)

	if err != nil {
		return nil, err
	}
	return resp, nil
}
<|endoftext|>


<commit_before>package runner

import (
	"context"
	"os"
	"os/signal"
	"path/filepath"
	"runtime"

	"github.com/Southclaws/sampctl/download"
	"github.com/Southclaws/sampctl/pkgcontext"
	"github.com/google/go-github/github"
	"github.com/pkg/errors"
	"go.uber.org/zap"
)

func Run() error {
	zap.L().Info("scavenge and survive runner initialising")

	dir, err := os.Getwd()
	if err != nil {
		return errors.Wrap(err, "failed to get current working directory")
	}

	forceBuild := false
	forceEnsure := false
	if isDirEmpty(dir) {
		zap.L().Info("Current directory is empty, cloning new copy of Scavenge and Survive")
		if err := Ensure(); err != nil {
			return errors.Wrap(err, "failed to ensure")
		}
		forceBuild = true
		forceEnsure = true
		zap.L().Info("doing first-time ensure and build")
	}

	if _, err := os.Stat(filepath.Join(dir, "dependencies")); err == os.ErrNotExist {
		forceBuild = true
		forceEnsure = true
		zap.L().Info("doing first-time ensure and build")
	}

	cacheDir, err := download.GetCacheDir()
	if err != nil {
		return errors.Wrap(err, "failed to get cache directory")
	}

	gh := github.NewClient(nil)

	pcx, err := pkgcontext.NewPackageContext(gh, nil, true, dir, runtime.GOOS, cacheDir, "")
	if err != nil {
		return errors.Wrap(err, "failed to interpret directory as Pawn package")
	}

	// pcx.Runtime = runtimeName
	pcx.CacheDir = cacheDir
	// pcx.BuildName = build
	pcx.ForceBuild = forceBuild
	pcx.ForceEnsure = forceEnsure
	pcx.BuildFile = "BUILD_NUMBER"
	pcx.Relative = true

	if err := pcx.RunPrepare(context.Background()); err != nil {
		return errors.Wrap(err, "failed to prepare runtime")
	}

	zap.L().Info("prepared runtime environment")

	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, os.Interrupt)

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	if os.Getenv("AUTO_BUILD") != "" {
		go RunWatcher(ctx, pcx)
	}

	go RunServer(ctx, os.Stdin, os.Stdout)
	go RunAPI(ctx)

	zap.L().Info("awaiting signals, cancellations or fatal errors")

	f := func() error {
		select {
		case s := <-sigs:
			return errors.Errorf("signal received: %s", s.String())

		case <-ctx.Done():
			return context.Canceled

		default:
			return nil
		}
	}

	for {
		if err := f(); err != nil {
			return err
		}
	}
}
<commit_msg>fix not exist check<commit_after>package runner

import (
	"context"
	"os"
	"os/signal"
	"path/filepath"
	"runtime"

	"github.com/Southclaws/sampctl/download"
	"github.com/Southclaws/sampctl/pkgcontext"
	"github.com/google/go-github/github"
	"github.com/pkg/errors"
	"go.uber.org/zap"
)

func Run() error {
	zap.L().Info("scavenge and survive runner initialising")

	dir, err := os.Getwd()
	if err != nil {
		return errors.Wrap(err, "failed to get current working directory")
	}

	forceBuild := false
	forceEnsure := false
	if isDirEmpty(dir) {
		zap.L().Info("Current directory is empty, cloning new copy of Scavenge and Survive")
		if err := Ensure(); err != nil {
			return errors.Wrap(err, "failed to ensure")
		}
		forceBuild = true
		forceEnsure = true
		zap.L().Info("doing first-time ensure and build")
	}

	if _, err := os.Stat(filepath.Join(dir, "dependencies")); os.IsNotExist(err) {
		forceBuild = true
		forceEnsure = true
		zap.L().Info("doing first-time ensure and build")
	}

	cacheDir, err := download.GetCacheDir()
	if err != nil {
		return errors.Wrap(err, "failed to get cache directory")
	}

	gh := github.NewClient(nil)

	pcx, err := pkgcontext.NewPackageContext(gh, nil, true, dir, runtime.GOOS, cacheDir, "")
	if err != nil {
		return errors.Wrap(err, "failed to interpret directory as Pawn package")
	}

	// pcx.Runtime = runtimeName
	pcx.CacheDir = cacheDir
	// pcx.BuildName = build
	pcx.ForceBuild = forceBuild
	pcx.ForceEnsure = forceEnsure
	pcx.BuildFile = "BUILD_NUMBER"
	pcx.Relative = true

	if err := pcx.RunPrepare(context.Background()); err != nil {
		return errors.Wrap(err, "failed to prepare runtime")
	}

	zap.L().Info("prepared runtime environment")

	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, os.Interrupt)

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	if os.Getenv("AUTO_BUILD") != "" {
		go RunWatcher(ctx, pcx)
	}

	go RunServer(ctx, os.Stdin, os.Stdout)
	go RunAPI(ctx)

	zap.L().Info("awaiting signals, cancellations or fatal errors")

	f := func() error {
		select {
		case s := <-sigs:
			return errors.Errorf("signal received: %s", s.String())

		case <-ctx.Done():
			return context.Canceled

		default:
			return nil
		}
	}

	for {
		if err := f(); err != nil {
			return err
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	//"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"sort"
	"strconv"
	"strings"
)

var importance map[string]float64

func StemQuery(query string) string {
	cmd := exec.Command(config.KrovetzBinary)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Fatal(err)
	}
	stdin, err := cmd.StdinPipe()
	if err != nil {
		log.Fatal(err)
	}
	if err := cmd.Start(); err != nil {
		log.Fatal(err)
	}

	io.WriteString(stdin, query)
	if err := stdin.Close(); err != nil {
		log.Fatal(err)
	}

	bytes, err := ioutil.ReadAll(stdout)
	if err != nil {
		log.Fatal(err)
	}
	output := string(bytes)

	if err := cmd.Wait(); err != nil {
		log.Fatal(err)
	}
	return strings.TrimSpace(output)
}

type QueryTerm struct {
	Term       string
	Importance float64
}

func (q QueryTerm) String() string {
	return q.Term
}

type ByImportance []QueryTerm

func (a ByImportance) Len() int           { return len(a) }
func (a ByImportance) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByImportance) Less(i, j int) bool { return a[i].Importance < a[j].Importance }

func TrimQuery(query string) string {
	if !config.TrimQueries {
		return query
	}

	stemmedQuery := StemQuery(query)
	stemmedTerms := strings.Split(stemmedQuery, " ")
	terms := strings.Split(query, " ")
	if len(terms) != len(stemmedTerms) {
		log.Printf("ERROR '%s' does not have the same number of terms after stemming to '%s'\n", query, stemmedQuery)
		return query
	}
	qt := make([]QueryTerm, len(terms))

	for i, _ := range terms {
		qt[i].Term = terms[i]
		imp, ok := importance[stemmedTerms[i]]
		if !ok {
			log.Printf("WARN: '%s' is not a term in the imporance map\n", stemmedTerms[i])
			imp = 0
		}
		qt[i].Importance = imp
	}

	sort.Sort(ByImportance(qt))

	/*res := "Terms: "
	for _, term := range qt {
		res += term.Term + "(" + fmt.Sprintf("%f", term.Importance) + ") "
	}
	log.Println(res) */

	trimmed := qt[:config.WordsPerQuery]
	result := ""
	for _, term := range trimmed {
		result += term.Term + " "
	}
	return result
}

func LoadImportance() {
	importance = make(map[string]float64)

	file, err := os.Open(config.MaxScores)
	if err != nil {
		log.Fatalf("Unable to open max scores file '%s': %s\n", config.MaxScores, err.Error())
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	log.Println("Initilaising Term Importance Map (takes around 1 min with default file)")
	for scanner.Scan() {
		line := scanner.Text()
		A := strings.Split(line, " ")
		if len(A) != 2 {
			log.Printf("MaxScores: Bad line '%s'\n", line)
			continue
		}
		if s, err := strconv.ParseFloat(A[1], 64); err == nil {
			importance[A[0]] = s
		} else {
			log.Printf("MaxScores: Bad float in line '%s'\n", line)
		}
	}
	log.Println("Term Importance Map Complete")
}
<commit_msg>Used stopwords to prune trimmed query<commit_after>package main

import (
	"bufio"
	//"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"sort"
	"strconv"
	"strings"
)

var importance map[string]float64

func StemQuery(query string) string {
	cmd := exec.Command(config.KrovetzBinary)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Fatal(err)
	}
	stdin, err := cmd.StdinPipe()
	if err != nil {
		log.Fatal(err)
	}
	if err := cmd.Start(); err != nil {
		log.Fatal(err)
	}

	io.WriteString(stdin, query)
	if err := stdin.Close(); err != nil {
		log.Fatal(err)
	}

	bytes, err := ioutil.ReadAll(stdout)
	if err != nil {
		log.Fatal(err)
	}
	output := string(bytes)

	if err := cmd.Wait(); err != nil {
		log.Fatal(err)
	}
	return strings.TrimSpace(output)
}

type QueryTerm struct {
	Term       string
	Importance float64
}

func (q QueryTerm) String() string {
	return q.Term
}

type ByImportance []QueryTerm

func (a ByImportance) Len() int           { return len(a) }
func (a ByImportance) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByImportance) Less(i, j int) bool { return a[i].Importance > a[j].Importance }

func TrimQuery(query string) string {
	if !config.TrimQueries {
		return query
	}

	stemmedQuery := query //StemQuery(query)
	stemmedTerms := strings.Split(stemmedQuery, " ")
	terms := strings.Split(query, " ")
	if len(terms) != len(stemmedTerms) {
		log.Printf("ERROR '%s' does not have the same number of terms after stemming to '%s'\n", query, stemmedQuery)
		return query
	}
	qts := make([]QueryTerm, len(terms), 0)

	for i, _ := range terms {
		if _, ok := stopwords[terms[i]]; ok {
			// This term is stopped

		}
		imp, ok := importance[stemmedTerms[i]]
		if !ok {
			log.Printf("WARN: '%s' is not a term in the imporance map\n", stemmedTerms[i])
			imp = 0
		}
		qt := QueryTerm{Term: terms[i], Importance: imp}
		qts = append(qts, qt)
	}

	sort.Sort(ByImportance(qts))
	/*
		res := "Terms: "
		for _, term := range qts {
			res += term.Term + "(" + fmt.Sprintf("%f", term.Importance) + ") "
		}
		log.Println(res)              */

	trimmed := qts[:config.WordsPerQuery]
	result := ""
	for _, term := range trimmed {
		result += term.Term + " "
	}
	return result
}

func LoadImportance() {
	importance = make(map[string]float64)

	file, err := os.Open(config.MaxScores)
	if err != nil {
		log.Fatalf("Unable to open max scores file '%s': %s\n", config.MaxScores, err.Error())
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	log.Println("Initilaising Term Importance Map (takes around 1 min with default file)")
	for scanner.Scan() {
		line := scanner.Text()
		A := strings.Split(line, " ")
		if len(A) != 2 {
			log.Printf("MaxScores: Bad line '%s'\n", line)
			continue
		}
		if s, err := strconv.ParseFloat(A[1], 64); err == nil {
			importance[A[0]] = s
		} else {
			log.Printf("MaxScores: Bad float in line '%s'\n", line)
		}
	}
	log.Println("Term Importance Map Complete")
}
<|endoftext|>


<commit_before>package queues

type Queue struct {
	elements []interface{}
}

func NewQueue() *Queue {
	return &Queue{elements: make([]interface{}, 0)}
}

func (queue *Queue) IsEmpty() bool {
	return len(queue.elements) == 0
}

func (queue *Queue) Push(element interface{}) {
	queue.elements = append(queue.elements, element)
}

func (queue *Queue) Pop() interface{} {
	element := queue.elements[0]
	if len(queue.elements) > 1 {
		queue.elements = queue.elements[1:]
	} else {
		queue.elements = make([]interface{}, 0)
	}
	return element
}
<commit_msg>queue.go: More idiomatic .Pop()<commit_after>package queues

type Queue struct {
	elements []interface{}
}

func NewQueue() *Queue {
	return &Queue{elements: make([]interface{}, 0)}
}

func (queue *Queue) IsEmpty() bool {
	return len(queue.elements) == 0
}

func (queue *Queue) Push(element interface{}) {
	queue.elements = append(queue.elements, element)
}

func (queue *Queue) Pop() interface{} {
	element := queue.elements[0]
	queue.elements = queue.elements[1:]
	return element
}
<|endoftext|>


<commit_before>/* greet.go */
package main

import (
  "os"
  "github.com/codegangsta/cli"
)

func main() {
  app := cli.NewApp()
  app.Name = "rabbitmqmgmt"
  app.Usage = "queue "
  app.Action = func(c *cli.Context) {
    println("testing!")
  }

  app.Run(os.Args)
}<commit_msg>testing subcommands<commit_after>/* greet.go */
package main

import (
  "os"
  "github.com/codegangsta/cli"
)

func main() {
  app := cli.NewApp()
  app.Name = "rabbitmqmgmt"
  app.Usage = "queue "
  app.Action = func(c *cli.Context) {
    println("testing!")
  }

  app.Commands = []cli.Command{
    {
        Name:      "queue",
        ShortName: "q",
        Usage:     "---",
        Action: func(c *cli.Context) {
          println("queue: ", c.Args().First())
        },
    },
    {
        Name:      "exchange",
        ShortName: "e",
        Usage:     "---",
        Action: func(c *cli.Context) {
          println("exchange: ", c.Args().First())
        },
    },
  }

  app.Run(os.Args)
}<|endoftext|>


<commit_before>package raster

import (
	"image"
	"fmt"
)

type Intersection struct {
	x float64
	winding int8
	next *Intersection
}

type Rasterizer struct {
	table []*Intersection
}

func NewRasterizer() *Rasterizer {
	r := new(Rasterizer)
	return r
}

func (r *Rasterizer) Fill(img *image.Alpha, p Polygon, nonZeroWindingRule bool) {
	r.table = make([]*Intersection, img.Bounds().Dy())
	var xmin, ymin, xmax, ymax float64
	xmin = p[0]
	ymin = p[1]
	xmax = xmin
	ymax = ymin
	var x, y float64
	for i := 2; i < len(p); i += 2 {
		x, y = p[i], p[i+1]
		if x > xmax {
			xmax = x
		} else if x < xmin {
			xmin = x
		}
		if y > ymax {
			ymax = y
		} else if y < ymin {
			ymin = y
		}
	}
	prevX, prevY := p[0], p[1]
	for i := 2; i < len(p); i += 2 {
		x, y = p[i], p[i+1]
		r.edge(prevX, prevY, x, y)
		prevX, prevY = x, y
	}
	if nonZeroWindingRule {
		r.scanNonZero(img, int(ymin+0.5), int(ymax+0.5))
	} else {
		r.scanEvenOdd(img, int(ymin+0.5), int(ymax+0.5))
	}
}

func max(i, j int) int {
	if i > j {
		return i
	}
	return j
}

func (r *Rasterizer) edge(x1, y1, x2, y2 float64) {
	var swap, dy float64
	var iy1, iy2 int
	var winding int8 = 1
	if y2 < y1 {
		swap = x1
		x1 = x2
		x2 = swap
		swap = y1
		y1 = y2
		y2 = swap
		winding = -1
	}
	iy1 = int(y1 + 0.5)
	iy2 = int(y2 + 0.5)
	dy = y2 - y1

	if dy == 0 {
		return
	}
	//idy = max(2, idy-1)

	x := x1
	dx := (x2 - x1) / dy

	for iy1 < iy2 {
		r.insert(x, iy1, winding)
		x += dx
		iy1++
	}
}

func (r *Rasterizer) insert(x float64, y int, winding int8) {
	i := &Intersection{x, winding, nil}
	if r.table[y] == nil {
		r.table[y] = i
		return
	}
	var prev *Intersection
	current := r.table[y]
	for current != nil && x > current.x {
		prev = current
		current = current.next
	}
	i.next = current
	if prev != nil {
		prev.next = i
		return
	}
}

func printIntersection(i *Intersection) {
	if i == nil {
		fmt.Print("nil")
	} else {
		for i != nil {
			fmt.Print(i.x, " ")
			i = i.next
		}
	}
	fmt.Println()
}

func (r *Rasterizer) scanEvenOdd(img *image.Alpha, ymin, ymax int) {
	var idx, ix1, ix2 int
	var i,j *Intersection
	fill := true
	pix := img.Pix[ymin*img.Stride:]
	for y := ymin; y < ymax; y++ {
		pix = pix[img.Stride:]
		i = r.table[y]
		if i != nil {
			fill = true
			j = i.next
			for j != nil {
				if fill {
					ix1 = int(i.x + 0.5)
					ix2 = int(j.x + 0.5)
					idx = ix2 - ix1
					if idx == 0 {
						continue
					}
					for ix1 < ix2 {
						pix[ix1] = 0xff
						ix1++
					}
				}
				fill = !fill
				i = j
				j = i.next
			}
		}
	}
}

func (r *Rasterizer) scanNonZero(img *image.Alpha, ymin, ymax int) {
	var ix1, ix2 int
	var i,j *Intersection
	pix := img.Pix[ymin*img.Stride:]
	var winding int8 = 0
	for y := ymin; y < ymax; y++ {
		pix = pix[img.Stride:]
		i = r.table[y]
		if i != nil {
			winding = i.winding
			j = i.next
			for j != nil {
				if winding != 0 {
					ix1 = int(i.x + 0.5)
					ix2 = int(j.x + 0.5)
					for ix1 < ix2 {
						pix[ix1] = 0xff
						ix1++
					}
				}
				winding = winding + j.winding
				i = j
				j = i.next
			}
		}
	}
}
<commit_msg>optimize bresenham<commit_after>package raster

import (
	"image"
	"fmt"
)

type Intersection struct {
	x int
	winding int8
	next *Intersection
}

type Rasterizer struct {
	table []*Intersection
}

func NewRasterizer() *Rasterizer {
	r := new(Rasterizer)
	return r
}

func (r *Rasterizer) Fill(img *image.Alpha, p Polygon, nonZeroWindingRule bool) {
	r.table = make([]*Intersection, img.Bounds().Dy())
	var xmin, ymin, xmax, ymax float64
	xmin = p[0]
	ymin = p[1]
	xmax = xmin
	ymax = ymin
	var x, y float64
	for i := 2; i < len(p); i += 2 {
		x, y = p[i], p[i+1]
		if x > xmax {
			xmax = x
		} else if x < xmin {
			xmin = x
		}
		if y > ymax {
			ymax = y
		} else if y < ymin {
			ymin = y
		}
	}
	fmt.Println("Begin create edges")
	prevX, prevY := p[0], p[1]
	for i := 2; i < len(p); i += 2 {
		x, y = p[i], p[i+1]
		r.edge(prevX, prevY, x, y)
		prevX, prevY = x, y
	}
	fmt.Println("End creating edges")
	if nonZeroWindingRule {
		r.scanNonZero(img, int(ymin+0.5), int(ymax+0.5))
	} else {
		r.scanEvenOdd(img, int(ymin+0.5), int(ymax+0.5))
	}
}

func max(i, j int) int {
	if i > j {
		return i
	}
	return j
}

func (r *Rasterizer) edge(xf1, yf1, xf2, yf2 float64) {
	x1, y1, x2, y2 := int(xf1+0.5), int(yf1+0.5), int(xf2+0.5),int(yf2+0.5)
	dx := abs(x2 - x1)
	dy := abs(y2 - y1)
	if dy == 0 {
		return;
	}
	var sx, sy int
	if x1 < x2 {
		sx = 1
	} else {
		sx = -1
	}
	if y1 < y2 {
		sy = 1
	} else {
		sy = -1
	}
	err := dx - dy
	r.insert(x1, y1, int8(sy))
	var e2 int
	for {
		if x1 == x2 && y1 == y2 {
			return
		}
		e2 = 2 * err
		if e2 > -dy {
			err = err - dy
			x1 = x1 + sx
		}
		if e2 < dx {
			err = err + dx
			y1 = y1 + sy
			r.insert(x1, y1, int8(sy))
		}
	}
}

func (r *Rasterizer) insert(x int, y int, winding int8) {
	i := &Intersection{x, winding, nil}
	if r.table[y] == nil {
		r.table[y] = i
		return
	}
	var prev *Intersection
	current := r.table[y]
	for current != nil && x > current.x {
		prev = current
		current = current.next
	}
	i.next = current
	if prev != nil {
		prev.next = i
		return
	}
}

func printIntersection(i *Intersection) {
	if i == nil {
		fmt.Print("nil")
	} else {
		for i != nil {
			fmt.Print(i.x, " ")
			i = i.next
		}
	}
	fmt.Println()
}

func (r *Rasterizer) scanEvenOdd(img *image.Alpha, ymin, ymax int) {
	var idx, ix1, ix2 int
	var i,j *Intersection
	fill := true
	pix := img.Pix[ymin*img.Stride:]
	for y := ymin; y < ymax; y++ {
		pix = pix[img.Stride:]
		i = r.table[y]
		if i != nil {
			fill = true
			j = i.next
			for j != nil {
				if fill {
					ix1 = i.x
					ix2 = j.x
					idx = ix2 - ix1
					if idx == 0 {
						continue
					}
					for ix1 < ix2 {
						pix[ix1] = 0xff
						ix1++
					}
				}
				fill = !fill
				i = j
				j = i.next
			}
		}
	}
}

func (r *Rasterizer) scanNonZero(img *image.Alpha, ymin, ymax int) {
	var ix1, ix2 int
	var i,j *Intersection
	pix := img.Pix[ymin*img.Stride:]
	var winding int8 = 0
	for y := ymin; y < ymax; y++ {
		pix = pix[img.Stride:]
		i = r.table[y]
		if i != nil {
			winding = i.winding
			j = i.next
			for j != nil {
				if winding != 0 {
					ix1 = i.x
					ix2 = j.x
					for ix1 < ix2 {
						pix[ix1] = 0xff
						ix1++
					}
				}
				winding = winding + j.winding
				i = j
				j = i.next
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"time"

	"github.com/schollz/croc/src/cli"
	"github.com/therecipe/qt/core"
	"github.com/therecipe/qt/widgets"
)

type CustomLabel struct {
	widgets.QLabel

	_ func(string) `signal:"updateTextFromGoroutine,auto(this.QLabel.setText)"` //TODO: support this.setText as well
}

func main() {
	if len(os.Args) > 1 {
		cli.Run()
		return
	}

	var isWorking bool
	app := widgets.NewQApplication(len(os.Args), os.Args)

	window := widgets.NewQMainWindow(nil, 0)
	window.SetFixedSize2(250, 200)
	window.SetWindowTitle("croc - secure data transfer")

	widget := widgets.NewQWidget(nil, 0)
	widget.SetLayout(widgets.NewQVBoxLayout())
	window.SetCentralWidget(widget)

	labels := make([]*CustomLabel, 3)
	for i := range labels {
		label := NewCustomLabel(nil, 0)
		label.SetAlignment(core.Qt__AlignCenter)
		widget.Layout().AddWidget(label)
		labels[i] = label
	}
	labels[0].SetText("Click 'Send' or 'Receive' to start")

	button := widgets.NewQPushButton2("Send file", nil)
	button.ConnectClicked(func(bool) {
		if isWorking {
			var info = widgets.NewQMessageBox(nil)
			info.SetWindowTitle("Info")
			info.SetText(fmt.Sprintf("Can only do one send or recieve at a time"))
			info.Exec()
			return
		}
		isWorking = true

		var fileDialog = widgets.NewQFileDialog2(nil, "Open file to send...", "", "")
		fileDialog.SetAcceptMode(widgets.QFileDialog__AcceptOpen)
		fileDialog.SetFileMode(widgets.QFileDialog__AnyFile)
		if fileDialog.Exec() != int(widgets.QDialog__Accepted) {
			return
		}
		var fn = fileDialog.SelectedFiles()[0]
		fmt.Println(fn)
		for i, label := range labels {
			go func(i int, label *CustomLabel) {
				var tick int
				for range time.NewTicker(time.Duration((i+1)*25) * time.Millisecond).C {
					tick++
					label.SetText(fmt.Sprintf("%v %v", tick, time.Now().UTC().Format("15:04:05.0000")))
				}
			}(i, label)
		}
	})
	widget.Layout().AddWidget(button)

	receiveButton := widgets.NewQPushButton2("Receive", nil)
	receiveButton.ConnectClicked(func(bool) {
		if isWorking {
			var info = widgets.NewQMessageBox(nil)
			info.SetWindowTitle("Info")
			info.SetText(fmt.Sprintf("Can only do one send or recieve at a time"))
			info.Exec()
			return
		}
		isWorking = true
		var codePhrase = widgets.QInputDialog_GetText(nil, "Enter code phrase", "",
			widgets.QLineEdit__Normal, "", true, core.Qt__Dialog, core.Qt__ImhNone)
		fmt.Println(codePhrase)
		var folderDialog = widgets.NewQFileDialog2(nil, "Open folder to receive file...", "", "")
		folderDialog.SetAcceptMode(widgets.QFileDialog__AcceptOpen)
		folderDialog.SetFileMode(widgets.QFileDialog__DirectoryOnly)
		if folderDialog.Exec() != int(widgets.QDialog__Accepted) {
			return
		}
		var fn = folderDialog.SelectedFiles()[0]
		fmt.Println(fn)
		for i, label := range labels {
			go func(i int, label *CustomLabel) {
				var tick int
				for range time.NewTicker(time.Duration((i+1)*25) * time.Millisecond).C {
					tick++
					label.SetText(fmt.Sprintf("%v %v", tick, time.Now().UTC().Format("15:04:05.0000")))
				}
			}(i, label)
		}
	})
	widget.Layout().AddWidget(receiveButton)

	window.Show()
	app.Exec()
}
<commit_msg>use build tags<commit_after>// +build wincroc

package main

import (
	"fmt"
	"os"
	"time"

	"github.com/schollz/croc/src/cli"
	"github.com/therecipe/qt/core"
	"github.com/therecipe/qt/widgets"
)

type CustomLabel struct {
	widgets.QLabel

	_ func(string) `signal:"updateTextFromGoroutine,auto(this.QLabel.setText)"` //TODO: support this.setText as well
}

func main() {
	if len(os.Args) > 1 {
		cli.Run()
		return
	}

	var isWorking bool
	app := widgets.NewQApplication(len(os.Args), os.Args)

	window := widgets.NewQMainWindow(nil, 0)
	window.SetFixedSize2(250, 200)
	window.SetWindowTitle("croc - secure data transfer")

	widget := widgets.NewQWidget(nil, 0)
	widget.SetLayout(widgets.NewQVBoxLayout())
	window.SetCentralWidget(widget)

	labels := make([]*CustomLabel, 3)
	for i := range labels {
		label := NewCustomLabel(nil, 0)
		label.SetAlignment(core.Qt__AlignCenter)
		widget.Layout().AddWidget(label)
		labels[i] = label
	}
	labels[0].SetText("Click 'Send' or 'Receive' to start")

	button := widgets.NewQPushButton2("Send file", nil)
	button.ConnectClicked(func(bool) {
		if isWorking {
			var info = widgets.NewQMessageBox(nil)
			info.SetWindowTitle("Info")
			info.SetText(fmt.Sprintf("Can only do one send or recieve at a time"))
			info.Exec()
			return
		}
		isWorking = true

		var fileDialog = widgets.NewQFileDialog2(nil, "Open file to send...", "", "")
		fileDialog.SetAcceptMode(widgets.QFileDialog__AcceptOpen)
		fileDialog.SetFileMode(widgets.QFileDialog__AnyFile)
		if fileDialog.Exec() != int(widgets.QDialog__Accepted) {
			return
		}
		var fn = fileDialog.SelectedFiles()[0]
		fmt.Println(fn)
		for i, label := range labels {
			go func(i int, label *CustomLabel) {
				var tick int
				for range time.NewTicker(time.Duration((i+1)*25) * time.Millisecond).C {
					tick++
					label.SetText(fmt.Sprintf("%v %v", tick, time.Now().UTC().Format("15:04:05.0000")))
				}
			}(i, label)
		}
	})
	widget.Layout().AddWidget(button)

	receiveButton := widgets.NewQPushButton2("Receive", nil)
	receiveButton.ConnectClicked(func(bool) {
		if isWorking {
			var info = widgets.NewQMessageBox(nil)
			info.SetWindowTitle("Info")
			info.SetText(fmt.Sprintf("Can only do one send or recieve at a time"))
			info.Exec()
			return
		}
		isWorking = true
		var codePhrase = widgets.QInputDialog_GetText(nil, "Enter code phrase", "",
			widgets.QLineEdit__Normal, "", true, core.Qt__Dialog, core.Qt__ImhNone)
		fmt.Println(codePhrase)
		var folderDialog = widgets.NewQFileDialog2(nil, "Open folder to receive file...", "", "")
		folderDialog.SetAcceptMode(widgets.QFileDialog__AcceptOpen)
		folderDialog.SetFileMode(widgets.QFileDialog__DirectoryOnly)
		if folderDialog.Exec() != int(widgets.QDialog__Accepted) {
			return
		}
		var fn = folderDialog.SelectedFiles()[0]
		fmt.Println(fn)
		for i, label := range labels {
			go func(i int, label *CustomLabel) {
				var tick int
				for range time.NewTicker(time.Duration((i+1)*25) * time.Millisecond).C {
					tick++
					label.SetText(fmt.Sprintf("%v %v", tick, time.Now().UTC().Format("15:04:05.0000")))
				}
			}(i, label)
		}
	})
	widget.Layout().AddWidget(receiveButton)

	window.Show()
	app.Exec()
}
<|endoftext|>


<commit_before>package swarm

import (
	"io"
	"net"
	"time"
	"xd/lib/bittorrent"
	"xd/lib/bittorrent/extensions"
	"xd/lib/common"
	"xd/lib/log"
)

// a peer connection
type PeerConn struct {
	inbound        bool
	closing        bool
	c              net.Conn
	id             common.PeerID
	t              *Torrent
	send           chan *common.WireMessage
	bf             *bittorrent.Bitfield
	peerChoke      bool
	peerInterested bool
	usChoke        bool
	usInterseted   bool
	Done           func()
	keepalive      *time.Ticker
	lastSend       time.Time
	tx             float32
	lastRecv       time.Time
	rx             float32
	r              *common.PieceRequest
	ourOpts        *extensions.ExtendedOptions
	theirOpts      *extensions.ExtendedOptions
}

// get stats for this connection
func (c *PeerConn) Stats() (st *PeerConnStats) {
	st = new(PeerConnStats)
	st.TX = c.tx
	st.RX = c.rx
	st.Addr = c.c.RemoteAddr().String()
	st.ID = c.id.String()
	return
}

func makePeerConn(c net.Conn, t *Torrent, id common.PeerID, ourOpts *extensions.ExtendedOptions) *PeerConn {
	p := new(PeerConn)
	p.c = c
	p.t = t
	p.ourOpts = ourOpts
	p.peerChoke = true
	p.usChoke = true
	copy(p.id[:], id[:])
	p.send = make(chan *common.WireMessage)
	p.keepalive = time.NewTicker(time.Minute)
	return p
}

func (c *PeerConn) start() {
	go c.runDownload()
	go c.runReader()
	go c.runWriter()
}

// queue a send of a bittorrent wire message to this peer
func (c *PeerConn) Send(msg *common.WireMessage) {
	if !c.closing {
		c.send <- msg
	}
}

// recv a bittorrent wire message (blocking)
func (c *PeerConn) Recv() (msg *common.WireMessage, err error) {
	// hack
	msg = common.KeepAlive()
	err = msg.Recv(c.c)
	log.Debugf("got %d bytes from %s", msg.Len(), c.id)
	now := time.Now()
	c.rx = float32(msg.Len()) / float32(now.Unix()-c.lastRecv.Unix())
	c.lastRecv = now
	return
}

// send choke
func (c *PeerConn) Choke() {
	if !c.usChoke {
		log.Debugf("choke peer %s", c.id.String())
		c.Send(common.NewWireMessage(common.Choke, nil))
		c.usChoke = true
	}
}

// send unchoke
func (c *PeerConn) Unchoke() {
	if c.usChoke {
		log.Debugf("unchoke peer %s", c.id.String())
		c.Send(common.NewWireMessage(common.UnChoke, nil))
		c.usChoke = false
	}
}

func (c *PeerConn) HasPiece(piece uint32) bool {
	if c.bf == nil {
		// no bitfield
		return false
	}
	return c.bf.Has(piece)
}

// return true if this peer is choking us otherwise return false
func (c *PeerConn) RemoteChoking() bool {
	return c.peerChoke
}

// return true if we are choking the remote peer otherwise return false
func (c *PeerConn) Chocking() bool {
	return c.usChoke
}

func (c *PeerConn) remoteUnchoke() {
	if !c.peerChoke {
		log.Warnf("remote peer %s sent multiple unchokes", c.id.String())
	}
	c.peerChoke = false
	log.Debugf("%s unchoked us", c.id.String())
}

func (c *PeerConn) remoteChoke() {
	if c.peerChoke {
		log.Warnf("remote peer %s sent multiple chokes", c.id.String())
	}
	c.peerChoke = true
	log.Debugf("%s choked us", c.id.String())
}

func (c *PeerConn) markInterested() {
	c.peerInterested = true
	log.Debugf("%s is interested", c.id.String())
}

func (c *PeerConn) markNotInterested() {
	c.peerInterested = false
	log.Debugf("%s is not interested", c.id.String())
}

func (c *PeerConn) Close() {
	if c.closing {
		return
	}
	c.closing = true
	c.t.pt.canceledRequest(c.r)
	c.keepalive.Stop()
	log.Debugf("%s closing connection", c.id.String())
	if c.send != nil {
		chnl := c.send
		c.send = nil
		close(chnl)
	}
	c.c.Close()
	if c.inbound {
		c.t.removeIBConn(c)
	} else {
		c.t.removeOBConn(c)
	}
}

// run read loop
func (c *PeerConn) runReader() {
	var err error
	for err == nil {
		var msg *common.WireMessage
		msg, err = c.Recv()
		if err == nil {
			if msg.KeepAlive() {
				log.Debugf("keepalive from %s", c.id)
				continue
			}
			msgid := msg.MessageID()
			log.Debugf("%s from %s", msgid.String(), c.id.String())
			if msgid == common.BitField {
				c.bf = bittorrent.NewBitfield(c.t.MetaInfo().Info.NumPieces(), msg.Payload())
				log.Debugf("got bitfield from %s", c.id.String())
				// TODO: determine if we are really interested
				m := common.NewInterested()
				c.Send(m)
				continue
			}
			if msgid == common.Choke {
				c.remoteChoke()
				continue
			}
			if msgid == common.UnChoke {
				c.remoteUnchoke()
				continue
			}
			if msgid == common.Interested {
				c.markInterested()
				c.Unchoke()
				continue
			}
			if msgid == common.NotInterested {
				c.markNotInterested()
				continue
			}
			if msgid == common.Request {
				ev := msg.GetPieceRequest()
				c.t.onPieceRequest(c, ev)
				continue
			}
			if msgid == common.Piece {
				d := msg.GetPieceData()
				if d == nil || d.Data == nil {
					log.Warnf("invalid piece data message from %s", c.id.String())
					c.Close()
				} else {
					if c.r != nil && c.r.Index == d.Index && c.r.Begin == d.Begin && c.r.Length == uint32(len(d.Data)) {
						c.t.pt.handlePieceData(d)
					} else {
						log.Warnf("unwarrented piece data from %s", c.id.String())
						c.Close()
					}
					c.r = nil
				}
				continue
			}
			if msgid == common.Have && c.bf != nil {
				// update bitfield
				c.bf.Set(msg.GetHave())
				if c.bf.AND(c.t.Bitfield()).CountSet() == 0 {
					// not interested
					c.Send(common.NewNotInterested())
				} else {
					c.Send(common.NewInterested())
				}
				continue
			}
			if msgid == common.Cancel {
				// TODO: check validity
				r := msg.GetPieceRequest()
				c.t.pt.canceledRequest(r)
				continue
			}
			if msgid == common.Extended {
				// handle extended options
				opts := extensions.FromWireMessage(msg)
				if opts == nil {
					log.Warnf("failed to parse extended options for %s", c.id.String())
				} else {
					c.handleExtendedOpts(opts)
				}
			}
		}
	}
	if err != io.EOF {
		log.Errorf("%s read error: %s", c.id, err)
	}
	c.Close()
}

func (c *PeerConn) handleExtendedOpts(opts *extensions.ExtendedOptions) {
	log.Debugf("got extended opts from '%s'", opts.Version)
}

func (c *PeerConn) sendKeepAlive() error {
	tm := time.Now().Add(0 - (time.Minute * 2))
	if c.lastSend.After(tm) {
		log.Debugf("send keepalive to %s", c.id.String())
		return common.KeepAlive().Send(c.c)
	}
	return nil
}

// run write loop
func (c *PeerConn) runWriter() {
	var err error
	for err == nil && !c.closing {
		select {
		case <-c.keepalive.C:
			err = c.sendKeepAlive()
		case msg, ok := <-c.send:
			if ok {
				now := time.Now()
				c.tx = float32(msg.Len()) / float32(now.Unix()-c.lastSend.Unix())
				c.lastSend = now
				if c.RemoteChoking() && msg.MessageID() == common.Request {
					// drop
					log.Debugf("drop request because choke")
					c.t.pt.canceledRequest(c.r)
					c.r = nil
				} else {
					err = msg.Send(c.c)
					log.Debugf("wrote message %s %d bytes", msg.MessageID(), msg.Len())
				}
			} else {
				break
			}
		}
	}
	c.Close()
}

// run download loop
func (c *PeerConn) runDownload() {
	for !c.t.Done() && c.send != nil {
		if c.RemoteChoking() {
			time.Sleep(time.Second)
			continue
		}
		// pending request
		if c.r != nil {
			time.Sleep(time.Millisecond * 100)
			continue
		}
		c.r = c.t.pt.nextRequestForDownload(c.bf)
		if c.r == nil {
			log.Debugf("no next piece to download for %s", c.id.String())
			time.Sleep(time.Second)
		} else {
			log.Debugf("ask %s for %d %d %d", c.id.String(), c.r.Index, c.r.Begin, c.r.Length)
			c.Send(c.r.ToWireMessage())
		}
	}
	if c.send == nil {
		c.Close()
		log.Debugf("peer %s disconnected trying reconnect", c.id.String())
		return
	}
	log.Debugf("peer %s is 'done'", c.id.String())

	// done downloading
	if c.Done != nil {
		c.Done()
	}
	log.Debugf("Close connection to %s", c.id.String())
	c.Close()
}
<commit_msg>don't close connection when done downloading<commit_after>package swarm

import (
	"io"
	"net"
	"time"
	"xd/lib/bittorrent"
	"xd/lib/bittorrent/extensions"
	"xd/lib/common"
	"xd/lib/log"
)

// a peer connection
type PeerConn struct {
	inbound        bool
	closing        bool
	c              net.Conn
	id             common.PeerID
	t              *Torrent
	send           chan *common.WireMessage
	bf             *bittorrent.Bitfield
	peerChoke      bool
	peerInterested bool
	usChoke        bool
	usInterseted   bool
	Done           func()
	keepalive      *time.Ticker
	lastSend       time.Time
	tx             float32
	lastRecv       time.Time
	rx             float32
	r              *common.PieceRequest
	ourOpts        *extensions.ExtendedOptions
	theirOpts      *extensions.ExtendedOptions
}

// get stats for this connection
func (c *PeerConn) Stats() (st *PeerConnStats) {
	st = new(PeerConnStats)
	st.TX = c.tx
	st.RX = c.rx
	st.Addr = c.c.RemoteAddr().String()
	st.ID = c.id.String()
	return
}

func makePeerConn(c net.Conn, t *Torrent, id common.PeerID, ourOpts *extensions.ExtendedOptions) *PeerConn {
	p := new(PeerConn)
	p.c = c
	p.t = t
	p.ourOpts = ourOpts
	p.peerChoke = true
	p.usChoke = true
	copy(p.id[:], id[:])
	p.send = make(chan *common.WireMessage)
	p.keepalive = time.NewTicker(time.Minute)
	return p
}

func (c *PeerConn) start() {
	go c.runDownload()
	go c.runReader()
	go c.runWriter()
}

// queue a send of a bittorrent wire message to this peer
func (c *PeerConn) Send(msg *common.WireMessage) {
	if !c.closing {
		c.send <- msg
	}
}

// recv a bittorrent wire message (blocking)
func (c *PeerConn) Recv() (msg *common.WireMessage, err error) {
	// hack
	msg = common.KeepAlive()
	err = msg.Recv(c.c)
	log.Debugf("got %d bytes from %s", msg.Len(), c.id)
	now := time.Now()
	c.rx = float32(msg.Len()) / float32(now.Unix()-c.lastRecv.Unix())
	c.lastRecv = now
	return
}

// send choke
func (c *PeerConn) Choke() {
	if !c.usChoke {
		log.Debugf("choke peer %s", c.id.String())
		c.Send(common.NewWireMessage(common.Choke, nil))
		c.usChoke = true
	}
}

// send unchoke
func (c *PeerConn) Unchoke() {
	if c.usChoke {
		log.Debugf("unchoke peer %s", c.id.String())
		c.Send(common.NewWireMessage(common.UnChoke, nil))
		c.usChoke = false
	}
}

func (c *PeerConn) HasPiece(piece uint32) bool {
	if c.bf == nil {
		// no bitfield
		return false
	}
	return c.bf.Has(piece)
}

// return true if this peer is choking us otherwise return false
func (c *PeerConn) RemoteChoking() bool {
	return c.peerChoke
}

// return true if we are choking the remote peer otherwise return false
func (c *PeerConn) Chocking() bool {
	return c.usChoke
}

func (c *PeerConn) remoteUnchoke() {
	if !c.peerChoke {
		log.Warnf("remote peer %s sent multiple unchokes", c.id.String())
	}
	c.peerChoke = false
	log.Debugf("%s unchoked us", c.id.String())
}

func (c *PeerConn) remoteChoke() {
	if c.peerChoke {
		log.Warnf("remote peer %s sent multiple chokes", c.id.String())
	}
	c.peerChoke = true
	log.Debugf("%s choked us", c.id.String())
}

func (c *PeerConn) markInterested() {
	c.peerInterested = true
	log.Debugf("%s is interested", c.id.String())
}

func (c *PeerConn) markNotInterested() {
	c.peerInterested = false
	log.Debugf("%s is not interested", c.id.String())
}

func (c *PeerConn) Close() {
	if c.closing {
		return
	}
	c.closing = true
	c.t.pt.canceledRequest(c.r)
	c.keepalive.Stop()
	log.Debugf("%s closing connection", c.id.String())
	if c.send != nil {
		chnl := c.send
		c.send = nil
		close(chnl)
	}
	c.c.Close()
	if c.inbound {
		c.t.removeIBConn(c)
	} else {
		c.t.removeOBConn(c)
	}
}

// run read loop
func (c *PeerConn) runReader() {
	var err error
	for err == nil {
		var msg *common.WireMessage
		msg, err = c.Recv()
		if err == nil {
			if msg.KeepAlive() {
				log.Debugf("keepalive from %s", c.id)
				continue
			}
			msgid := msg.MessageID()
			log.Debugf("%s from %s", msgid.String(), c.id.String())
			if msgid == common.BitField {
				c.bf = bittorrent.NewBitfield(c.t.MetaInfo().Info.NumPieces(), msg.Payload())
				log.Debugf("got bitfield from %s", c.id.String())
				// TODO: determine if we are really interested
				m := common.NewInterested()
				c.Send(m)
				continue
			}
			if msgid == common.Choke {
				c.remoteChoke()
				continue
			}
			if msgid == common.UnChoke {
				c.remoteUnchoke()
				continue
			}
			if msgid == common.Interested {
				c.markInterested()
				c.Unchoke()
				continue
			}
			if msgid == common.NotInterested {
				c.markNotInterested()
				continue
			}
			if msgid == common.Request {
				ev := msg.GetPieceRequest()
				c.t.onPieceRequest(c, ev)
				continue
			}
			if msgid == common.Piece {
				d := msg.GetPieceData()
				if d == nil || d.Data == nil {
					log.Warnf("invalid piece data message from %s", c.id.String())
					c.Close()
				} else {
					if c.r != nil && c.r.Index == d.Index && c.r.Begin == d.Begin && c.r.Length == uint32(len(d.Data)) {
						c.t.pt.handlePieceData(d)
					} else {
						log.Warnf("unwarrented piece data from %s", c.id.String())
						c.Close()
					}
					c.r = nil
				}
				continue
			}
			if msgid == common.Have && c.bf != nil {
				// update bitfield
				c.bf.Set(msg.GetHave())
				if c.bf.AND(c.t.Bitfield()).CountSet() == 0 {
					// not interested
					c.Send(common.NewNotInterested())
				} else {
					c.Send(common.NewInterested())
				}
				continue
			}
			if msgid == common.Cancel {
				// TODO: check validity
				r := msg.GetPieceRequest()
				c.t.pt.canceledRequest(r)
				continue
			}
			if msgid == common.Extended {
				// handle extended options
				opts := extensions.FromWireMessage(msg)
				if opts == nil {
					log.Warnf("failed to parse extended options for %s", c.id.String())
				} else {
					c.handleExtendedOpts(opts)
				}
			}
		}
	}
	if err != io.EOF {
		log.Errorf("%s read error: %s", c.id, err)
	}
	c.Close()
}

func (c *PeerConn) handleExtendedOpts(opts *extensions.ExtendedOptions) {
	log.Debugf("got extended opts from '%s'", opts.Version)
}

func (c *PeerConn) sendKeepAlive() error {
	tm := time.Now().Add(0 - (time.Minute * 2))
	if c.lastSend.After(tm) {
		log.Debugf("send keepalive to %s", c.id.String())
		return common.KeepAlive().Send(c.c)
	}
	return nil
}

// run write loop
func (c *PeerConn) runWriter() {
	var err error
	for err == nil && !c.closing {
		select {
		case <-c.keepalive.C:
			err = c.sendKeepAlive()
		case msg, ok := <-c.send:
			if ok {
				now := time.Now()
				c.tx = float32(msg.Len()) / float32(now.Unix()-c.lastSend.Unix())
				c.lastSend = now
				if c.RemoteChoking() && msg.MessageID() == common.Request {
					// drop
					log.Debugf("drop request because choke")
					c.t.pt.canceledRequest(c.r)
					c.r = nil
				} else {
					err = msg.Send(c.c)
					log.Debugf("wrote message %s %d bytes", msg.MessageID(), msg.Len())
				}
			} else {
				break
			}
		}
	}
	c.Close()
}

// run download loop
func (c *PeerConn) runDownload() {
	for !c.t.Done() && c.send != nil {
		if c.RemoteChoking() {
			time.Sleep(time.Second)
			continue
		}
		// pending request
		if c.r != nil {
			time.Sleep(time.Millisecond * 100)
			continue
		}
		c.r = c.t.pt.nextRequestForDownload(c.bf)
		if c.r == nil {
			log.Debugf("no next piece to download for %s", c.id.String())
			time.Sleep(time.Second)
		} else {
			log.Debugf("ask %s for %d %d %d", c.id.String(), c.r.Index, c.r.Begin, c.r.Length)
			c.Send(c.r.ToWireMessage())
		}
	}
	if c.send == nil {
		c.Close()
		log.Debugf("peer %s disconnected trying reconnect", c.id.String())
		return
	}
	log.Debugf("peer %s is 'done'", c.id.String())

	// done downloading
	if c.Done != nil {
		c.Done()
	}
}
<|endoftext|>


<commit_before>//go:build integration

/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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

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

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

package integration

import (
	"context"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"testing"
)

// stderrAllow are regular expressions acceptable to find in normal stderr
var stderrAllow = []string{
	// kubectl out of date warning
	`kubectl`,
	// slow docker warning
	`slow|long time|Restarting the docker service may improve`,
	// don't care if we can't push images to other profiles
	`cache_images.go:.*error getting status`,
	// don't care if we can't push images to other profiles which are deleted.
	`cache_images.go:.*Failed to load profile`,
	// "! 'docker' driver reported a issue that could affect the performance."
	`docker.*issue.*performance`,
	// "* Suggestion: enable overlayfs kernel module on your Linux"
	`Suggestion.*overlayfs`,
	// "! docker is currently using the btrfs storage driver, consider switching to overlay2 for better performance"
	`docker.*btrfs storage driver`,
	// jenkins VMs (debian 9) cgoups don't allow setting memory
	`Your cgroup does not allow setting memory.`,
	// progress bar output
	`    > .*`,
}

// stderrAllowRe combines rootCauses into a single regex
var stderrAllowRe = regexp.MustCompile(strings.Join(stderrAllow, "|"))

// TestErrorSpam asserts that there are no unexpected errors displayed in minikube command outputs.
func TestErrorSpam(t *testing.T) {
	if NoneDriver() {
		t.Skip("none driver always shows a warning")
	}

	profile := UniqueProfileName("nospam")
	ctx, cancel := context.WithTimeout(context.Background(), Minutes(25))
	defer CleanupWithLogs(t, profile, cancel)

	logDir := filepath.Join(os.TempDir(), profile)
	if err := os.MkdirAll(logDir, 0755); err != nil {
		t.Fatalf("Unable to make logDir %s: %v", logDir, err)
	}
	defer os.RemoveAll(logDir)

	t.Run("setup", func(t *testing.T) {
		// This should likely use multi-node once it's ready
		// use `--log_dir` flag to run isolated and avoid race condition - ie, failing to clean up (locked) log files created by other concurently-run tests, or counting them in results
		args := append([]string{"start", "-p", profile, "-n=1", "--memory=2250", "--wait=false", fmt.Sprintf("--log_dir=%s", logDir)}, StartArgs()...)

		rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
		if err != nil {
			t.Errorf("%q failed: %v", rr.Command(), err)
		}

		stdout := rr.Stdout.String()
		stderr := rr.Stderr.String()

		for _, line := range strings.Split(stderr, "\n") {
			if stderrAllowRe.MatchString(line) {
				t.Logf("acceptable stderr: %q", line)
				continue
			}

			if len(strings.TrimSpace(line)) > 0 {
				t.Errorf("unexpected stderr: %q", line)
			}
		}

		for _, line := range strings.Split(stdout, "\n") {
			keywords := []string{"error", "fail", "warning", "conflict"}
			for _, keyword := range keywords {
				if strings.Contains(line, keyword) {
					t.Errorf("unexpected %q in stdout: %q", keyword, line)
				}
			}
		}

		if t.Failed() {
			t.Logf("minikube stdout:\n%s", stdout)
			t.Logf("minikube stderr:\n%s", stderr)
		}

		steps := []string{
			"Generating certificates and keys ...",
			"Booting up control plane ...",
			"Configuring RBAC rules ...",
		}
		for _, step := range steps {
			if !strings.Contains(stdout, step) {
				t.Errorf("missing kubeadm init sub-step %q", step)
			}
		}
	})

	logTests := []struct {
		command string
		args    []string
	}{
		{
			command: "start",
			args:    []string{"--dry-run"},
		},
		{
			command: "status",
		}, {
			command: "pause",
		}, {
			command: "unpause",
		}, {
			command: "stop",
		},
	}

	for _, test := range logTests {
		t.Run(test.command, func(t *testing.T) {
			// before starting the test, ensure no other logs from the current command are written
			logFiles, err := getLogFiles(logDir, test.command)
			if err != nil {
				t.Fatalf("failed to get old log files for command %s : %v", test.command, err)
			}
			cleanupLogFiles(t, logFiles)

			args := []string{"-p", profile, "--log_dir", logDir, test.command}
			args = append(args, test.args...)

			// run command twice
			for i := 0; i < 2; i++ {
				rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
				if err != nil {
					t.Logf("%q failed: %v", rr.Command(), err)
				}
			}

			// check if one log file exists
			if err := checkLogFileCount(test.command, logDir, 1); err != nil {
				t.Fatal(err)
			}

			// get log file generated above
			logFiles, err = getLogFiles(logDir, test.command)
			if err != nil {
				t.Fatalf("failed to get new log files for command %s : %v", test.command, err)
			}

			// make file at least 1024 KB in size
			if err := os.Truncate(logFiles[0], 2e7); err != nil {
				t.Fatalf("failed to increase file size to 1024KB: %v", err)
			}

			// run command again
			rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
			if err != nil {
				t.Logf("%q failed: %v", rr.Command(), err)
			}

			// check if two log files exist now
			if err := checkLogFileCount(test.command, logDir, 2); err != nil {
				t.Fatal(err)
			}
		})

	}
}

func getLogFiles(logDir string, command string) ([]string, error) {
	return filepath.Glob(filepath.Join(logDir, fmt.Sprintf("minikube_%s*", command)))
}

func checkLogFileCount(command string, logDir string, expectedNumberOfLogFiles int) error {
	// get log files generated above
	logFiles, err := getLogFiles(logDir, command)
	if err != nil {
		return fmt.Errorf("failed to get new log files for command %s : %v", command, err)
	}

	if len(logFiles) != expectedNumberOfLogFiles {
		return fmt.Errorf("Running cmd %q resulted in %d log file(s); expected: %d", command, len(logFiles), expectedNumberOfLogFiles)
	}

	return nil
}

// cleanupLogFiles removes logfiles generated during testing
func cleanupLogFiles(t *testing.T, logFiles []string) {
	t.Logf("Cleaning up %d logfile(s) ...", len(logFiles))
	for _, logFile := range logFiles {
		if err := os.Remove(logFile); err != nil {
			t.Logf("failed to cleanup log file: %s : %v", logFile, err)
		}
	}
}
<commit_msg>fix TestErrorSpam failing on warning<commit_after>//go:build integration

/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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

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

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

package integration

import (
	"context"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"testing"
)

// stderrAllow are regular expressions acceptable to find in normal stderr
var stderrAllow = []string{
	// kubectl out of date warning
	`kubectl`,
	// slow docker warning
	`slow|long time|Restarting the docker service may improve`,
	// don't care if we can't push images to other profiles
	`cache_images.go:.*error getting status`,
	// don't care if we can't push images to other profiles which are deleted.
	`cache_images.go:.*Failed to load profile`,
	// "! 'docker' driver reported a issue that could affect the performance."
	`docker.*issue.*performance`,
	// "* Suggestion: enable overlayfs kernel module on your Linux"
	`Suggestion.*overlayfs`,
	// "! docker is currently using the btrfs storage driver, consider switching to overlay2 for better performance"
	`docker.*btrfs storage driver`,
	// jenkins VMs (debian 9) cgoups don't allow setting memory
	`Your cgroup does not allow setting memory.`,
	// progress bar output
	`    > .*`,
	// Warning of issues with specific Kubernetes versions
	`Kubernetes .* has a known `,
}

// stderrAllowRe combines rootCauses into a single regex
var stderrAllowRe = regexp.MustCompile(strings.Join(stderrAllow, "|"))

// TestErrorSpam asserts that there are no unexpected errors displayed in minikube command outputs.
func TestErrorSpam(t *testing.T) {
	if NoneDriver() {
		t.Skip("none driver always shows a warning")
	}

	profile := UniqueProfileName("nospam")
	ctx, cancel := context.WithTimeout(context.Background(), Minutes(25))
	defer CleanupWithLogs(t, profile, cancel)

	logDir := filepath.Join(os.TempDir(), profile)
	if err := os.MkdirAll(logDir, 0755); err != nil {
		t.Fatalf("Unable to make logDir %s: %v", logDir, err)
	}
	defer os.RemoveAll(logDir)

	t.Run("setup", func(t *testing.T) {
		// This should likely use multi-node once it's ready
		// use `--log_dir` flag to run isolated and avoid race condition - ie, failing to clean up (locked) log files created by other concurently-run tests, or counting them in results
		args := append([]string{"start", "-p", profile, "-n=1", "--memory=2250", "--wait=false", fmt.Sprintf("--log_dir=%s", logDir)}, StartArgs()...)

		rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
		if err != nil {
			t.Errorf("%q failed: %v", rr.Command(), err)
		}

		stdout := rr.Stdout.String()
		stderr := rr.Stderr.String()

		for _, line := range strings.Split(stderr, "\n") {
			if stderrAllowRe.MatchString(line) {
				t.Logf("acceptable stderr: %q", line)
				continue
			}

			if len(strings.TrimSpace(line)) > 0 {
				t.Errorf("unexpected stderr: %q", line)
			}
		}

		for _, line := range strings.Split(stdout, "\n") {
			keywords := []string{"error", "fail", "warning", "conflict"}
			for _, keyword := range keywords {
				if strings.Contains(line, keyword) {
					t.Errorf("unexpected %q in stdout: %q", keyword, line)
				}
			}
		}

		if t.Failed() {
			t.Logf("minikube stdout:\n%s", stdout)
			t.Logf("minikube stderr:\n%s", stderr)
		}

		steps := []string{
			"Generating certificates and keys ...",
			"Booting up control plane ...",
			"Configuring RBAC rules ...",
		}
		for _, step := range steps {
			if !strings.Contains(stdout, step) {
				t.Errorf("missing kubeadm init sub-step %q", step)
			}
		}
	})

	logTests := []struct {
		command string
		args    []string
	}{
		{
			command: "start",
			args:    []string{"--dry-run"},
		},
		{
			command: "status",
		}, {
			command: "pause",
		}, {
			command: "unpause",
		}, {
			command: "stop",
		},
	}

	for _, test := range logTests {
		t.Run(test.command, func(t *testing.T) {
			// before starting the test, ensure no other logs from the current command are written
			logFiles, err := getLogFiles(logDir, test.command)
			if err != nil {
				t.Fatalf("failed to get old log files for command %s : %v", test.command, err)
			}
			cleanupLogFiles(t, logFiles)

			args := []string{"-p", profile, "--log_dir", logDir, test.command}
			args = append(args, test.args...)

			// run command twice
			for i := 0; i < 2; i++ {
				rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
				if err != nil {
					t.Logf("%q failed: %v", rr.Command(), err)
				}
			}

			// check if one log file exists
			if err := checkLogFileCount(test.command, logDir, 1); err != nil {
				t.Fatal(err)
			}

			// get log file generated above
			logFiles, err = getLogFiles(logDir, test.command)
			if err != nil {
				t.Fatalf("failed to get new log files for command %s : %v", test.command, err)
			}

			// make file at least 1024 KB in size
			if err := os.Truncate(logFiles[0], 2e7); err != nil {
				t.Fatalf("failed to increase file size to 1024KB: %v", err)
			}

			// run command again
			rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
			if err != nil {
				t.Logf("%q failed: %v", rr.Command(), err)
			}

			// check if two log files exist now
			if err := checkLogFileCount(test.command, logDir, 2); err != nil {
				t.Fatal(err)
			}
		})

	}
}

func getLogFiles(logDir string, command string) ([]string, error) {
	return filepath.Glob(filepath.Join(logDir, fmt.Sprintf("minikube_%s*", command)))
}

func checkLogFileCount(command string, logDir string, expectedNumberOfLogFiles int) error {
	// get log files generated above
	logFiles, err := getLogFiles(logDir, command)
	if err != nil {
		return fmt.Errorf("failed to get new log files for command %s : %v", command, err)
	}

	if len(logFiles) != expectedNumberOfLogFiles {
		return fmt.Errorf("Running cmd %q resulted in %d log file(s); expected: %d", command, len(logFiles), expectedNumberOfLogFiles)
	}

	return nil
}

// cleanupLogFiles removes logfiles generated during testing
func cleanupLogFiles(t *testing.T, logFiles []string) {
	t.Logf("Cleaning up %d logfile(s) ...", len(logFiles))
	for _, logFile := range logFiles {
		if err := os.Remove(logFile); err != nil {
			t.Logf("failed to cleanup log file: %s : %v", logFile, err)
		}
	}
}
<|endoftext|>