<commit_before>// +build !ignore_autogenerated

/*
Copyright 2016 The Kubernetes Authors.

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

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

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

// This file was autogenerated by conversion-gen. Do not edit it manually!

package v1beta1

import (
	federation "k8s.io/kubernetes/federation/apis/federation"
	api "k8s.io/kubernetes/pkg/api"
	v1 "k8s.io/kubernetes/pkg/api/v1"
	conversion "k8s.io/kubernetes/pkg/conversion"
	runtime "k8s.io/kubernetes/pkg/runtime"
)

func init() {
	SchemeBuilder.Register(RegisterConversions)
}

// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(scheme *runtime.Scheme) error {
	return scheme.AddGeneratedConversionFuncs(
		Convert_v1beta1_Cluster_To_federation_Cluster,
		Convert_federation_Cluster_To_v1beta1_Cluster,
		Convert_v1beta1_ClusterCondition_To_federation_ClusterCondition,
		Convert_federation_ClusterCondition_To_v1beta1_ClusterCondition,
		Convert_v1beta1_ClusterList_To_federation_ClusterList,
		Convert_federation_ClusterList_To_v1beta1_ClusterList,
		Convert_v1beta1_ClusterSpec_To_federation_ClusterSpec,
		Convert_federation_ClusterSpec_To_v1beta1_ClusterSpec,
		Convert_v1beta1_ClusterStatus_To_federation_ClusterStatus,
		Convert_federation_ClusterStatus_To_v1beta1_ClusterStatus,
		Convert_v1beta1_ServerAddressByClientCIDR_To_federation_ServerAddressByClientCIDR,
		Convert_federation_ServerAddressByClientCIDR_To_v1beta1_ServerAddressByClientCIDR,
	)
}

func autoConvert_v1beta1_Cluster_To_federation_Cluster(in *Cluster, out *federation.Cluster, s conversion.Scope) error {
	// TODO: Inefficient conversion - can we improve it?
	if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
		return err
	}
	if err := Convert_v1beta1_ClusterSpec_To_federation_ClusterSpec(&in.Spec, &out.Spec, s); err != nil {
		return err
	}
	if err := Convert_v1beta1_ClusterStatus_To_federation_ClusterStatus(&in.Status, &out.Status, s); err != nil {
		return err
	}
	return nil
}

func Convert_v1beta1_Cluster_To_federation_Cluster(in *Cluster, out *federation.Cluster, s conversion.Scope) error {
	return autoConvert_v1beta1_Cluster_To_federation_Cluster(in, out, s)
}

func autoConvert_federation_Cluster_To_v1beta1_Cluster(in *federation.Cluster, out *Cluster, s conversion.Scope) error {
	// TODO: Inefficient conversion - can we improve it?
	if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
		return err
	}
	if err := Convert_federation_ClusterSpec_To_v1beta1_ClusterSpec(&in.Spec, &out.Spec, s); err != nil {
		return err
	}
	if err := Convert_federation_ClusterStatus_To_v1beta1_ClusterStatus(&in.Status, &out.Status, s); err != nil {
		return err
	}
	return nil
}

func Convert_federation_Cluster_To_v1beta1_Cluster(in *federation.Cluster, out *Cluster, s conversion.Scope) error {
	return autoConvert_federation_Cluster_To_v1beta1_Cluster(in, out, s)
}

func autoConvert_v1beta1_ClusterCondition_To_federation_ClusterCondition(in *ClusterCondition, out *federation.ClusterCondition, s conversion.Scope) error {
	out.Type = federation.ClusterConditionType(in.Type)
	out.Status = api.ConditionStatus(in.Status)
	out.LastProbeTime = in.LastProbeTime
	out.LastTransitionTime = in.LastTransitionTime
	out.Reason = in.Reason
	out.Message = in.Message
	return nil
}

func Convert_v1beta1_ClusterCondition_To_federation_ClusterCondition(in *ClusterCondition, out *federation.ClusterCondition, s conversion.Scope) error {
	return autoConvert_v1beta1_ClusterCondition_To_federation_ClusterCondition(in, out, s)
}

func autoConvert_federation_ClusterCondition_To_v1beta1_ClusterCondition(in *federation.ClusterCondition, out *ClusterCondition, s conversion.Scope) error {
	out.Type = ClusterConditionType(in.Type)
	out.Status = v1.ConditionStatus(in.Status)
	out.LastProbeTime = in.LastProbeTime
	out.LastTransitionTime = in.LastTransitionTime
	out.Reason = in.Reason
	out.Message = in.Message
	return nil
}

func Convert_federation_ClusterCondition_To_v1beta1_ClusterCondition(in *federation.ClusterCondition, out *ClusterCondition, s conversion.Scope) error {
	return autoConvert_federation_ClusterCondition_To_v1beta1_ClusterCondition(in, out, s)
}

func autoConvert_v1beta1_ClusterList_To_federation_ClusterList(in *ClusterList, out *federation.ClusterList, s conversion.Scope) error {
	out.ListMeta = in.ListMeta
	if in.Items != nil {
		in, out := &in.Items, &out.Items
		*out = make([]federation.Cluster, len(*in))
		for i := range *in {
			if err := Convert_v1beta1_Cluster_To_federation_Cluster(&(*in)[i], &(*out)[i], s); err != nil {
				return err
			}
		}
	} else {
		out.Items = nil
	}
	return nil
}

func Convert_v1beta1_ClusterList_To_federation_ClusterList(in *ClusterList, out *federation.ClusterList, s conversion.Scope) error {
	return autoConvert_v1beta1_ClusterList_To_federation_ClusterList(in, out, s)
}

func autoConvert_federation_ClusterList_To_v1beta1_ClusterList(in *federation.ClusterList, out *ClusterList, s conversion.Scope) error {
	out.ListMeta = in.ListMeta
	if in.Items != nil {
		in, out := &in.Items, &out.Items
		*out = make([]Cluster, len(*in))
		for i := range *in {
			if err := Convert_federation_Cluster_To_v1beta1_Cluster(&(*in)[i], &(*out)[i], s); err != nil {
				return err
			}
		}
	} else {
		out.Items = nil
	}
	return nil
}

func Convert_federation_ClusterList_To_v1beta1_ClusterList(in *federation.ClusterList, out *ClusterList, s conversion.Scope) error {
	return autoConvert_federation_ClusterList_To_v1beta1_ClusterList(in, out, s)
}

func autoConvert_v1beta1_ClusterSpec_To_federation_ClusterSpec(in *ClusterSpec, out *federation.ClusterSpec, s conversion.Scope) error {
	if in.ServerAddressByClientCIDRs != nil {
		in, out := &in.ServerAddressByClientCIDRs, &out.ServerAddressByClientCIDRs
		*out = make([]federation.ServerAddressByClientCIDR, len(*in))
		for i := range *in {
			if err := Convert_v1beta1_ServerAddressByClientCIDR_To_federation_ServerAddressByClientCIDR(&(*in)[i], &(*out)[i], s); err != nil {
				return err
			}
		}
	} else {
		out.ServerAddressByClientCIDRs = nil
	}
	if in.SecretRef != nil {
		in, out := &in.SecretRef, &out.SecretRef
		*out = new(api.LocalObjectReference)
		// TODO: Inefficient conversion - can we improve it?
		if err := s.Convert(*in, *out, 0); err != nil {
			return err
		}
	} else {
		out.SecretRef = nil
	}
	return nil
}

func Convert_v1beta1_ClusterSpec_To_federation_ClusterSpec(in *ClusterSpec, out *federation.ClusterSpec, s conversion.Scope) error {
	return autoConvert_v1beta1_ClusterSpec_To_federation_ClusterSpec(in, out, s)
}

func autoConvert_federation_ClusterSpec_To_v1beta1_ClusterSpec(in *federation.ClusterSpec, out *ClusterSpec, s conversion.Scope) error {
	if in.ServerAddressByClientCIDRs != nil {
		in, out := &in.ServerAddressByClientCIDRs, &out.ServerAddressByClientCIDRs
		*out = make([]ServerAddressByClientCIDR, len(*in))
		for i := range *in {
			if err := Convert_federation_ServerAddressByClientCIDR_To_v1beta1_ServerAddressByClientCIDR(&(*in)[i], &(*out)[i], s); err != nil {
				return err
			}
		}
	} else {
		out.ServerAddressByClientCIDRs = nil
	}
	if in.SecretRef != nil {
		in, out := &in.SecretRef, &out.SecretRef
		*out = new(v1.LocalObjectReference)
		// TODO: Inefficient conversion - can we improve it?
		if err := s.Convert(*in, *out, 0); err != nil {
			return err
		}
	} else {
		out.SecretRef = nil
	}
	return nil
}

func Convert_federation_ClusterSpec_To_v1beta1_ClusterSpec(in *federation.ClusterSpec, out *ClusterSpec, s conversion.Scope) error {
	return autoConvert_federation_ClusterSpec_To_v1beta1_ClusterSpec(in, out, s)
}

func autoConvert_v1beta1_ClusterStatus_To_federation_ClusterStatus(in *ClusterStatus, out *federation.ClusterStatus, s conversion.Scope) error {
	if in.Conditions != nil {
		in, out := &in.Conditions, &out.Conditions
		*out = make([]federation.ClusterCondition, len(*in))
		for i := range *in {
			if err := Convert_v1beta1_ClusterCondition_To_federation_ClusterCondition(&(*in)[i], &(*out)[i], s); err != nil {
				return err
			}
		}
	} else {
		out.Conditions = nil
	}
	out.Zones = in.Zones
	out.Region = in.Region
	return nil
}

func Convert_v1beta1_ClusterStatus_To_federation_ClusterStatus(in *ClusterStatus, out *federation.ClusterStatus, s conversion.Scope) error {
	return autoConvert_v1beta1_ClusterStatus_To_federation_ClusterStatus(in, out, s)
}

func autoConvert_federation_ClusterStatus_To_v1beta1_ClusterStatus(in *federation.ClusterStatus, out *ClusterStatus, s conversion.Scope) error {
	if in.Conditions != nil {
		in, out := &in.Conditions, &out.Conditions
		*out = make([]ClusterCondition, len(*in))
		for i := range *in {
			if err := Convert_federation_ClusterCondition_To_v1beta1_ClusterCondition(&(*in)[i], &(*out)[i], s); err != nil {
				return err
			}
		}
	} else {
		out.Conditions = nil
	}
	out.Zones = in.Zones
	out.Region = in.Region
	return nil
}

func Convert_federation_ClusterStatus_To_v1beta1_ClusterStatus(in *federation.ClusterStatus, out *ClusterStatus, s conversion.Scope) error {
	return autoConvert_federation_ClusterStatus_To_v1beta1_ClusterStatus(in, out, s)
}

func autoConvert_v1beta1_ServerAddressByClientCIDR_To_federation_ServerAddressByClientCIDR(in *ServerAddressByClientCIDR, out *federation.ServerAddressByClientCIDR, s conversion.Scope) error {
	out.ClientCIDR = in.ClientCIDR
	out.ServerAddress = in.ServerAddress
	return nil
}

func Convert_v1beta1_ServerAddressByClientCIDR_To_federation_ServerAddressByClientCIDR(in *ServerAddressByClientCIDR, out *federation.ServerAddressByClientCIDR, s conversion.Scope) error {
	return autoConvert_v1beta1_ServerAddressByClientCIDR_To_federation_ServerAddressByClientCIDR(in, out, s)
}

func autoConvert_federation_ServerAddressByClientCIDR_To_v1beta1_ServerAddressByClientCIDR(in *federation.ServerAddressByClientCIDR, out *ServerAddressByClientCIDR, s conversion.Scope) error {
	out.ClientCIDR = in.ClientCIDR
	out.ServerAddress = in.ServerAddress
	return nil
}

func Convert_federation_ServerAddressByClientCIDR_To_v1beta1_ServerAddressByClientCIDR(in *federation.ServerAddressByClientCIDR, out *ServerAddressByClientCIDR, s conversion.Scope) error {
	return autoConvert_federation_ServerAddressByClientCIDR_To_v1beta1_ServerAddressByClientCIDR(in, out, s)
}
<commit_msg>generated: alternative unsafe conversions<commit_after>// +build !ignore_autogenerated

/*
Copyright 2016 The Kubernetes Authors.

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

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

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

// This file was autogenerated by conversion-gen. Do not edit it manually!

package v1beta1

import (
	federation "k8s.io/kubernetes/federation/apis/federation"
	api "k8s.io/kubernetes/pkg/api"
	v1 "k8s.io/kubernetes/pkg/api/v1"
	conversion "k8s.io/kubernetes/pkg/conversion"
	runtime "k8s.io/kubernetes/pkg/runtime"
	unsafe "unsafe"
)

func init() {
	SchemeBuilder.Register(RegisterConversions)
}

// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(scheme *runtime.Scheme) error {
	return scheme.AddGeneratedConversionFuncs(
		Convert_v1beta1_Cluster_To_federation_Cluster,
		Convert_federation_Cluster_To_v1beta1_Cluster,
		Convert_v1beta1_ClusterCondition_To_federation_ClusterCondition,
		Convert_federation_ClusterCondition_To_v1beta1_ClusterCondition,
		Convert_v1beta1_ClusterList_To_federation_ClusterList,
		Convert_federation_ClusterList_To_v1beta1_ClusterList,
		Convert_v1beta1_ClusterSpec_To_federation_ClusterSpec,
		Convert_federation_ClusterSpec_To_v1beta1_ClusterSpec,
		Convert_v1beta1_ClusterStatus_To_federation_ClusterStatus,
		Convert_federation_ClusterStatus_To_v1beta1_ClusterStatus,
		Convert_v1beta1_ServerAddressByClientCIDR_To_federation_ServerAddressByClientCIDR,
		Convert_federation_ServerAddressByClientCIDR_To_v1beta1_ServerAddressByClientCIDR,
	)
}

func autoConvert_v1beta1_Cluster_To_federation_Cluster(in *Cluster, out *federation.Cluster, s conversion.Scope) error {
	// TODO: Inefficient conversion - can we improve it?
	if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
		return err
	}
	if err := Convert_v1beta1_ClusterSpec_To_federation_ClusterSpec(&in.Spec, &out.Spec, s); err != nil {
		return err
	}
	if err := Convert_v1beta1_ClusterStatus_To_federation_ClusterStatus(&in.Status, &out.Status, s); err != nil {
		return err
	}
	return nil
}

func Convert_v1beta1_Cluster_To_federation_Cluster(in *Cluster, out *federation.Cluster, s conversion.Scope) error {
	return autoConvert_v1beta1_Cluster_To_federation_Cluster(in, out, s)
}

func autoConvert_federation_Cluster_To_v1beta1_Cluster(in *federation.Cluster, out *Cluster, s conversion.Scope) error {
	// TODO: Inefficient conversion - can we improve it?
	if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
		return err
	}
	if err := Convert_federation_ClusterSpec_To_v1beta1_ClusterSpec(&in.Spec, &out.Spec, s); err != nil {
		return err
	}
	if err := Convert_federation_ClusterStatus_To_v1beta1_ClusterStatus(&in.Status, &out.Status, s); err != nil {
		return err
	}
	return nil
}

func Convert_federation_Cluster_To_v1beta1_Cluster(in *federation.Cluster, out *Cluster, s conversion.Scope) error {
	return autoConvert_federation_Cluster_To_v1beta1_Cluster(in, out, s)
}

func autoConvert_v1beta1_ClusterCondition_To_federation_ClusterCondition(in *ClusterCondition, out *federation.ClusterCondition, s conversion.Scope) error {
	out.Type = federation.ClusterConditionType(in.Type)
	out.Status = api.ConditionStatus(in.Status)
	out.LastProbeTime = in.LastProbeTime
	out.LastTransitionTime = in.LastTransitionTime
	out.Reason = in.Reason
	out.Message = in.Message
	return nil
}

func Convert_v1beta1_ClusterCondition_To_federation_ClusterCondition(in *ClusterCondition, out *federation.ClusterCondition, s conversion.Scope) error {
	return autoConvert_v1beta1_ClusterCondition_To_federation_ClusterCondition(in, out, s)
}

func autoConvert_federation_ClusterCondition_To_v1beta1_ClusterCondition(in *federation.ClusterCondition, out *ClusterCondition, s conversion.Scope) error {
	out.Type = ClusterConditionType(in.Type)
	out.Status = v1.ConditionStatus(in.Status)
	out.LastProbeTime = in.LastProbeTime
	out.LastTransitionTime = in.LastTransitionTime
	out.Reason = in.Reason
	out.Message = in.Message
	return nil
}

func Convert_federation_ClusterCondition_To_v1beta1_ClusterCondition(in *federation.ClusterCondition, out *ClusterCondition, s conversion.Scope) error {
	return autoConvert_federation_ClusterCondition_To_v1beta1_ClusterCondition(in, out, s)
}

func autoConvert_v1beta1_ClusterList_To_federation_ClusterList(in *ClusterList, out *federation.ClusterList, s conversion.Scope) error {
	out.ListMeta = in.ListMeta
	out.Items = *(*[]federation.Cluster)(unsafe.Pointer(&in.Items))
	return nil
}

func Convert_v1beta1_ClusterList_To_federation_ClusterList(in *ClusterList, out *federation.ClusterList, s conversion.Scope) error {
	return autoConvert_v1beta1_ClusterList_To_federation_ClusterList(in, out, s)
}

func autoConvert_federation_ClusterList_To_v1beta1_ClusterList(in *federation.ClusterList, out *ClusterList, s conversion.Scope) error {
	out.ListMeta = in.ListMeta
	out.Items = *(*[]Cluster)(unsafe.Pointer(&in.Items))
	return nil
}

func Convert_federation_ClusterList_To_v1beta1_ClusterList(in *federation.ClusterList, out *ClusterList, s conversion.Scope) error {
	return autoConvert_federation_ClusterList_To_v1beta1_ClusterList(in, out, s)
}

func autoConvert_v1beta1_ClusterSpec_To_federation_ClusterSpec(in *ClusterSpec, out *federation.ClusterSpec, s conversion.Scope) error {
	out.ServerAddressByClientCIDRs = *(*[]federation.ServerAddressByClientCIDR)(unsafe.Pointer(&in.ServerAddressByClientCIDRs))
	out.SecretRef = (*api.LocalObjectReference)(unsafe.Pointer(in.SecretRef))
	return nil
}

func Convert_v1beta1_ClusterSpec_To_federation_ClusterSpec(in *ClusterSpec, out *federation.ClusterSpec, s conversion.Scope) error {
	return autoConvert_v1beta1_ClusterSpec_To_federation_ClusterSpec(in, out, s)
}

func autoConvert_federation_ClusterSpec_To_v1beta1_ClusterSpec(in *federation.ClusterSpec, out *ClusterSpec, s conversion.Scope) error {
	out.ServerAddressByClientCIDRs = *(*[]ServerAddressByClientCIDR)(unsafe.Pointer(&in.ServerAddressByClientCIDRs))
	out.SecretRef = (*v1.LocalObjectReference)(unsafe.Pointer(in.SecretRef))
	return nil
}

func Convert_federation_ClusterSpec_To_v1beta1_ClusterSpec(in *federation.ClusterSpec, out *ClusterSpec, s conversion.Scope) error {
	return autoConvert_federation_ClusterSpec_To_v1beta1_ClusterSpec(in, out, s)
}

func autoConvert_v1beta1_ClusterStatus_To_federation_ClusterStatus(in *ClusterStatus, out *federation.ClusterStatus, s conversion.Scope) error {
	out.Conditions = *(*[]federation.ClusterCondition)(unsafe.Pointer(&in.Conditions))
	out.Zones = *(*[]string)(unsafe.Pointer(&in.Zones))
	out.Region = in.Region
	return nil
}

func Convert_v1beta1_ClusterStatus_To_federation_ClusterStatus(in *ClusterStatus, out *federation.ClusterStatus, s conversion.Scope) error {
	return autoConvert_v1beta1_ClusterStatus_To_federation_ClusterStatus(in, out, s)
}

func autoConvert_federation_ClusterStatus_To_v1beta1_ClusterStatus(in *federation.ClusterStatus, out *ClusterStatus, s conversion.Scope) error {
	out.Conditions = *(*[]ClusterCondition)(unsafe.Pointer(&in.Conditions))
	out.Zones = *(*[]string)(unsafe.Pointer(&in.Zones))
	out.Region = in.Region
	return nil
}

func Convert_federation_ClusterStatus_To_v1beta1_ClusterStatus(in *federation.ClusterStatus, out *ClusterStatus, s conversion.Scope) error {
	return autoConvert_federation_ClusterStatus_To_v1beta1_ClusterStatus(in, out, s)
}

func autoConvert_v1beta1_ServerAddressByClientCIDR_To_federation_ServerAddressByClientCIDR(in *ServerAddressByClientCIDR, out *federation.ServerAddressByClientCIDR, s conversion.Scope) error {
	out.ClientCIDR = in.ClientCIDR
	out.ServerAddress = in.ServerAddress
	return nil
}

func Convert_v1beta1_ServerAddressByClientCIDR_To_federation_ServerAddressByClientCIDR(in *ServerAddressByClientCIDR, out *federation.ServerAddressByClientCIDR, s conversion.Scope) error {
	return autoConvert_v1beta1_ServerAddressByClientCIDR_To_federation_ServerAddressByClientCIDR(in, out, s)
}

func autoConvert_federation_ServerAddressByClientCIDR_To_v1beta1_ServerAddressByClientCIDR(in *federation.ServerAddressByClientCIDR, out *ServerAddressByClientCIDR, s conversion.Scope) error {
	out.ClientCIDR = in.ClientCIDR
	out.ServerAddress = in.ServerAddress
	return nil
}

func Convert_federation_ServerAddressByClientCIDR_To_v1beta1_ServerAddressByClientCIDR(in *federation.ServerAddressByClientCIDR, out *ServerAddressByClientCIDR, s conversion.Scope) error {
	return autoConvert_federation_ServerAddressByClientCIDR_To_v1beta1_ServerAddressByClientCIDR(in, out, s)
}
<|endoftext|>


<commit_before>// +build go1.13
// +build !386

/*
 *
 * Copyright 2021 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// Package xds_test contains e2e tests for xDS use.
package xds_test

import (
	"context"
	"fmt"
	"net"
	"sync"
	"testing"

	v3listenerpb "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"

	"google.golang.org/grpc"
	"google.golang.org/grpc/connectivity"
	"google.golang.org/grpc/credentials/insecure"
	xdscreds "google.golang.org/grpc/credentials/xds"
	"google.golang.org/grpc/internal/testutils"
	testpb "google.golang.org/grpc/test/grpc_testing"
	"google.golang.org/grpc/xds"
	xdstestutils "google.golang.org/grpc/xds/internal/testutils"
	"google.golang.org/grpc/xds/internal/testutils/e2e"
)

// A convenience typed used to keep track of mode changes on multiple listeners.
type modeTracker struct {
	mu       sync.Mutex
	modes    map[string]xds.ServingMode
	updateCh *testutils.Channel
}

func newModeTracker() *modeTracker {
	return &modeTracker{
		modes:    make(map[string]xds.ServingMode),
		updateCh: testutils.NewChannel(),
	}
}

func (mt *modeTracker) updateMode(ctx context.Context, addr net.Addr, mode xds.ServingMode) {
	mt.mu.Lock()
	defer mt.mu.Unlock()

	mt.modes[addr.String()] = mode
	// Sometimes we could get state updates which are not expected by the test.
	// Using `Send()` here would block in that case and cause the whole test to
	// hang and will eventually only timeout when the `-timeout` passed to `go
	// test` elapses. Using `SendContext()` here instead fails the test within a
	// reasonable timeout.
	mt.updateCh.SendContext(ctx, nil)
}

func (mt *modeTracker) getMode(addr net.Addr) xds.ServingMode {
	mt.mu.Lock()
	defer mt.mu.Unlock()
	return mt.modes[addr.String()]
}

func (mt *modeTracker) waitForUpdate(ctx context.Context) error {
	_, err := mt.updateCh.Receive(ctx)
	if err != nil {
		return fmt.Errorf("error when waiting for a mode change update: %v", err)
	}
	return nil
}

// TestServerSideXDS_ServingModeChanges tests the serving mode functionality in
// xDS enabled gRPC servers. It verifies that appropriate mode changes happen in
// the server, and also verifies behavior of clientConns under these modes.
func (s) TestServerSideXDS_ServingModeChanges(t *testing.T) {
	// Configure xDS credentials to be used on the server-side.
	creds, err := xdscreds.NewServerCredentials(xdscreds.ServerOptions{
		FallbackCreds: insecure.NewCredentials(),
	})
	if err != nil {
		t.Fatal(err)
	}

	// Create a server option to get notified about serving mode changes.
	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
	defer cancel()
	modeTracker := newModeTracker()
	modeChangeOpt := xds.ServingModeCallback(func(addr net.Addr, args xds.ServingModeChangeArgs) {
		t.Logf("serving mode for listener %q changed to %q, err: %v", addr.String(), args.Mode, args.Err)
		modeTracker.updateMode(ctx, addr, args.Mode)
	})

	// Initialize an xDS-enabled gRPC server and register the stubServer on it.
	server := xds.NewGRPCServer(grpc.Creds(creds), modeChangeOpt, xds.BootstrapContentsForTesting(bootstrapContents))
	defer server.Stop()
	testpb.RegisterTestServiceServer(server, &testService{})

	// Create two local listeners and pass it to Serve().
	lis1, err := xdstestutils.LocalTCPListener()
	if err != nil {
		t.Fatalf("testutils.LocalTCPListener() failed: %v", err)
	}
	lis2, err := xdstestutils.LocalTCPListener()
	if err != nil {
		t.Fatalf("testutils.LocalTCPListener() failed: %v", err)
	}

	// Setup the management server to respond with server-side Listener
	// resources for both listeners.
	host1, port1, err := hostPortFromListener(lis1)
	if err != nil {
		t.Fatalf("failed to retrieve host and port of server: %v", err)
	}
	listener1 := e2e.DefaultServerListener(host1, port1, e2e.SecurityLevelNone)
	host2, port2, err := hostPortFromListener(lis2)
	if err != nil {
		t.Fatalf("failed to retrieve host and port of server: %v", err)
	}
	listener2 := e2e.DefaultServerListener(host2, port2, e2e.SecurityLevelNone)
	resources := e2e.UpdateOptions{
		NodeID:    xdsClientNodeID,
		Listeners: []*v3listenerpb.Listener{listener1, listener2},
	}
	if err := managementServer.Update(resources); err != nil {
		t.Fatal(err)
	}

	go func() {
		if err := server.Serve(lis1); err != nil {
			t.Errorf("Serve() failed: %v", err)
		}
	}()
	go func() {
		if err := server.Serve(lis2); err != nil {
			t.Errorf("Serve() failed: %v", err)
		}
	}()

	// Wait for both listeners to move to "serving" mode.
	if err := waitForModeChange(ctx, modeTracker, lis1.Addr(), xds.ServingModeServing); err != nil {
		t.Fatal(err)
	}
	if err := waitForModeChange(ctx, modeTracker, lis2.Addr(), xds.ServingModeServing); err != nil {
		t.Fatal(err)
	}

	// Create a ClientConn to the first listener and make a successful RPCs.
	cc1, err := grpc.DialContext(ctx, lis1.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		t.Fatalf("failed to dial local test server: %v", err)
	}
	defer cc1.Close()

	client1 := testpb.NewTestServiceClient(cc1)
	if _, err := client1.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil {
		t.Fatalf("rpc EmptyCall() failed: %v", err)
	}

	// Create a ClientConn to the second listener and make a successful RPCs.
	cc2, err := grpc.DialContext(ctx, lis2.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		t.Fatalf("failed to dial local test server: %v", err)
	}
	defer cc2.Close()

	client2 := testpb.NewTestServiceClient(cc2)
	if _, err := client2.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil {
		t.Fatalf("rpc EmptyCall() failed: %v", err)
	}

	// Update the management server to remove the second listener resource. This
	// should push only the second listener into "not-serving" mode.
	if err := managementServer.Update(e2e.UpdateOptions{
		NodeID:    xdsClientNodeID,
		Listeners: []*v3listenerpb.Listener{listener1},
	}); err != nil {
		t.Error(err)
	}
	if err := waitForModeChange(ctx, modeTracker, lis2.Addr(), xds.ServingModeNotServing); err != nil {
		t.Fatal(err)
	}

	// Make sure cc1 is still in READY state, while cc2 has moved out of READY.
	if s := cc1.GetState(); s != connectivity.Ready {
		t.Fatalf("clientConn1 state is %s, want %s", s, connectivity.Ready)
	}
	if !cc2.WaitForStateChange(ctx, connectivity.Ready) {
		t.Fatal("clientConn2 failed to move out of READY")
	}

	// Make sure RPCs succeed on cc1 and fail on cc2.
	if _, err := client1.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil {
		t.Fatalf("rpc EmptyCall() failed: %v", err)
	}
	if _, err := client2.EmptyCall(ctx, &testpb.Empty{}); err == nil {
		t.Fatal("rpc EmptyCall() succeeded when expected to fail")
	}

	// Update the management server to remove the first listener resource as
	// well. This should push the first listener into "not-serving" mode. Second
	// listener is already in "not-serving" mode.
	if err := managementServer.Update(e2e.UpdateOptions{
		NodeID:    xdsClientNodeID,
		Listeners: []*v3listenerpb.Listener{},
	}); err != nil {
		t.Error(err)
	}
	if err := waitForModeChange(ctx, modeTracker, lis1.Addr(), xds.ServingModeNotServing); err != nil {
		t.Fatal(err)
	}

	// Make sure cc1 has moved out of READY.
	if !cc1.WaitForStateChange(ctx, connectivity.Ready) {
		t.Fatal("clientConn1 failed to move out of READY")
	}

	// Make sure RPCs fail on both.
	if _, err := client1.EmptyCall(ctx, &testpb.Empty{}); err == nil {
		t.Fatal("rpc EmptyCall() succeeded when expected to fail")
	}
	if _, err := client2.EmptyCall(ctx, &testpb.Empty{}); err == nil {
		t.Fatal("rpc EmptyCall() succeeded when expected to fail")
	}

	// Make sure new connection attempts to "not-serving" servers fail. We use a
	// short timeout since we expect this to fail.
	sCtx, sCancel := context.WithTimeout(ctx, defaultTestShortTimeout)
	defer sCancel()
	if _, err := grpc.DialContext(sCtx, lis1.Addr().String(), grpc.WithBlock(), grpc.WithTransportCredentials(insecure.NewCredentials())); err == nil {
		t.Fatal("successfully created clientConn to a server in \"not-serving\" state")
	}

	// Update the management server with both listener resources.
	if err := managementServer.Update(e2e.UpdateOptions{
		NodeID:    xdsClientNodeID,
		Listeners: []*v3listenerpb.Listener{listener1, listener2},
	}); err != nil {
		t.Error(err)
	}

	// Wait for both listeners to move to "serving" mode.
	if err := waitForModeChange(ctx, modeTracker, lis1.Addr(), xds.ServingModeServing); err != nil {
		t.Fatal(err)
	}
	if err := waitForModeChange(ctx, modeTracker, lis2.Addr(), xds.ServingModeServing); err != nil {
		t.Fatal(err)
	}

	// The clientConns created earlier should be able to make RPCs now.
	if _, err := client1.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil {
		t.Fatalf("rpc EmptyCall() failed: %v", err)
	}
	if _, err := client2.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil {
		t.Fatalf("rpc EmptyCall() failed: %v", err)
	}
}

func waitForModeChange(ctx context.Context, modeTracker *modeTracker, addr net.Addr, wantMode xds.ServingMode) error {
	for {
		if gotMode := modeTracker.getMode(addr); gotMode == wantMode {
			return nil
		}
		if err := modeTracker.waitForUpdate(ctx); err != nil {
			return err
		}
	}
}
<commit_msg>xds: deflake Test/ServerSideXDS_ServingModeChanges (#4689)<commit_after>// +build go1.13
// +build !386

/*
 *
 * Copyright 2021 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// Package xds_test contains e2e tests for xDS use.
package xds_test

import (
	"context"
	"fmt"
	"net"
	"sync"
	"testing"
	"time"

	v3listenerpb "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	xdscreds "google.golang.org/grpc/credentials/xds"
	"google.golang.org/grpc/internal/testutils"
	testpb "google.golang.org/grpc/test/grpc_testing"
	"google.golang.org/grpc/xds"
	xdstestutils "google.golang.org/grpc/xds/internal/testutils"
	"google.golang.org/grpc/xds/internal/testutils/e2e"
)

// A convenience typed used to keep track of mode changes on multiple listeners.
type modeTracker struct {
	mu       sync.Mutex
	modes    map[string]xds.ServingMode
	updateCh *testutils.Channel
}

func newModeTracker() *modeTracker {
	return &modeTracker{
		modes:    make(map[string]xds.ServingMode),
		updateCh: testutils.NewChannel(),
	}
}

func (mt *modeTracker) updateMode(ctx context.Context, addr net.Addr, mode xds.ServingMode) {
	mt.mu.Lock()
	defer mt.mu.Unlock()

	mt.modes[addr.String()] = mode
	// Sometimes we could get state updates which are not expected by the test.
	// Using `Send()` here would block in that case and cause the whole test to
	// hang and will eventually only timeout when the `-timeout` passed to `go
	// test` elapses. Using `SendContext()` here instead fails the test within a
	// reasonable timeout.
	mt.updateCh.SendContext(ctx, nil)
}

func (mt *modeTracker) getMode(addr net.Addr) xds.ServingMode {
	mt.mu.Lock()
	defer mt.mu.Unlock()
	return mt.modes[addr.String()]
}

func (mt *modeTracker) waitForUpdate(ctx context.Context) error {
	_, err := mt.updateCh.Receive(ctx)
	if err != nil {
		return fmt.Errorf("error when waiting for a mode change update: %v", err)
	}
	return nil
}

// TestServerSideXDS_ServingModeChanges tests the serving mode functionality in
// xDS enabled gRPC servers. It verifies that appropriate mode changes happen in
// the server, and also verifies behavior of clientConns under these modes.
func (s) TestServerSideXDS_ServingModeChanges(t *testing.T) {
	// Configure xDS credentials to be used on the server-side.
	creds, err := xdscreds.NewServerCredentials(xdscreds.ServerOptions{
		FallbackCreds: insecure.NewCredentials(),
	})
	if err != nil {
		t.Fatal(err)
	}

	// Create a server option to get notified about serving mode changes.
	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
	defer cancel()
	modeTracker := newModeTracker()
	modeChangeOpt := xds.ServingModeCallback(func(addr net.Addr, args xds.ServingModeChangeArgs) {
		t.Logf("serving mode for listener %q changed to %q, err: %v", addr.String(), args.Mode, args.Err)
		modeTracker.updateMode(ctx, addr, args.Mode)
	})

	// Initialize an xDS-enabled gRPC server and register the stubServer on it.
	server := xds.NewGRPCServer(grpc.Creds(creds), modeChangeOpt, xds.BootstrapContentsForTesting(bootstrapContents))
	defer server.Stop()
	testpb.RegisterTestServiceServer(server, &testService{})

	// Create two local listeners and pass it to Serve().
	lis1, err := xdstestutils.LocalTCPListener()
	if err != nil {
		t.Fatalf("testutils.LocalTCPListener() failed: %v", err)
	}
	lis2, err := xdstestutils.LocalTCPListener()
	if err != nil {
		t.Fatalf("testutils.LocalTCPListener() failed: %v", err)
	}

	// Setup the management server to respond with server-side Listener
	// resources for both listeners.
	host1, port1, err := hostPortFromListener(lis1)
	if err != nil {
		t.Fatalf("failed to retrieve host and port of server: %v", err)
	}
	listener1 := e2e.DefaultServerListener(host1, port1, e2e.SecurityLevelNone)
	host2, port2, err := hostPortFromListener(lis2)
	if err != nil {
		t.Fatalf("failed to retrieve host and port of server: %v", err)
	}
	listener2 := e2e.DefaultServerListener(host2, port2, e2e.SecurityLevelNone)
	resources := e2e.UpdateOptions{
		NodeID:    xdsClientNodeID,
		Listeners: []*v3listenerpb.Listener{listener1, listener2},
	}
	if err := managementServer.Update(resources); err != nil {
		t.Fatal(err)
	}

	go func() {
		if err := server.Serve(lis1); err != nil {
			t.Errorf("Serve() failed: %v", err)
		}
	}()
	go func() {
		if err := server.Serve(lis2); err != nil {
			t.Errorf("Serve() failed: %v", err)
		}
	}()

	// Wait for both listeners to move to "serving" mode.
	if err := waitForModeChange(ctx, modeTracker, lis1.Addr(), xds.ServingModeServing); err != nil {
		t.Fatal(err)
	}
	if err := waitForModeChange(ctx, modeTracker, lis2.Addr(), xds.ServingModeServing); err != nil {
		t.Fatal(err)
	}

	// Create a ClientConn to the first listener and make a successful RPCs.
	cc1, err := grpc.Dial(lis1.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		t.Fatalf("failed to dial local test server: %v", err)
	}
	defer cc1.Close()
	waitForSuccessfulRPC(ctx, t, cc1)

	// Create a ClientConn to the second listener and make a successful RPCs.
	cc2, err := grpc.Dial(lis2.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		t.Fatalf("failed to dial local test server: %v", err)
	}
	defer cc2.Close()
	waitForSuccessfulRPC(ctx, t, cc2)

	// Update the management server to remove the second listener resource. This
	// should push only the second listener into "not-serving" mode.
	if err := managementServer.Update(e2e.UpdateOptions{
		NodeID:    xdsClientNodeID,
		Listeners: []*v3listenerpb.Listener{listener1},
	}); err != nil {
		t.Error(err)
	}
	if err := waitForModeChange(ctx, modeTracker, lis2.Addr(), xds.ServingModeNotServing); err != nil {
		t.Fatal(err)
	}

	// Make sure RPCs succeed on cc1 and fail on cc2.
	waitForSuccessfulRPC(ctx, t, cc1)
	waitForFailedRPC(ctx, t, cc2)

	// Update the management server to remove the first listener resource as
	// well. This should push the first listener into "not-serving" mode. Second
	// listener is already in "not-serving" mode.
	if err := managementServer.Update(e2e.UpdateOptions{
		NodeID:    xdsClientNodeID,
		Listeners: []*v3listenerpb.Listener{},
	}); err != nil {
		t.Error(err)
	}
	if err := waitForModeChange(ctx, modeTracker, lis1.Addr(), xds.ServingModeNotServing); err != nil {
		t.Fatal(err)
	}

	// Make sure RPCs fail on both.
	waitForFailedRPC(ctx, t, cc1)
	waitForFailedRPC(ctx, t, cc2)

	// Make sure new connection attempts to "not-serving" servers fail. We use a
	// short timeout since we expect this to fail.
	sCtx, sCancel := context.WithTimeout(ctx, defaultTestShortTimeout)
	defer sCancel()
	if _, err := grpc.DialContext(sCtx, lis1.Addr().String(), grpc.WithBlock(), grpc.WithTransportCredentials(insecure.NewCredentials())); err == nil {
		t.Fatal("successfully created clientConn to a server in \"not-serving\" state")
	}

	// Update the management server with both listener resources.
	if err := managementServer.Update(e2e.UpdateOptions{
		NodeID:    xdsClientNodeID,
		Listeners: []*v3listenerpb.Listener{listener1, listener2},
	}); err != nil {
		t.Error(err)
	}

	// Wait for both listeners to move to "serving" mode.
	if err := waitForModeChange(ctx, modeTracker, lis1.Addr(), xds.ServingModeServing); err != nil {
		t.Fatal(err)
	}
	if err := waitForModeChange(ctx, modeTracker, lis2.Addr(), xds.ServingModeServing); err != nil {
		t.Fatal(err)
	}

	// The clientConns created earlier should be able to make RPCs now.
	waitForSuccessfulRPC(ctx, t, cc1)
	waitForSuccessfulRPC(ctx, t, cc2)
}

func waitForModeChange(ctx context.Context, modeTracker *modeTracker, addr net.Addr, wantMode xds.ServingMode) error {
	for {
		if gotMode := modeTracker.getMode(addr); gotMode == wantMode {
			return nil
		}
		if err := modeTracker.waitForUpdate(ctx); err != nil {
			return err
		}
	}
}

func waitForSuccessfulRPC(ctx context.Context, t *testing.T, cc *grpc.ClientConn) {
	t.Helper()

	c := testpb.NewTestServiceClient(cc)
	if _, err := c.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil {
		t.Fatalf("rpc EmptyCall() failed: %v", err)
	}
}

func waitForFailedRPC(ctx context.Context, t *testing.T, cc *grpc.ClientConn) {
	t.Helper()

	c := testpb.NewTestServiceClient(cc)
	ticker := time.NewTimer(10 * time.Millisecond)
	defer ticker.Stop()
	for {
		select {
		case <-ctx.Done():
			t.Fatalf("failure when waiting for RPCs to fail: %v", ctx.Err())
		case <-ticker.C:
			if _, err := c.EmptyCall(ctx, &testpb.Empty{}); err != nil {
				return
			}
		}
	}
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"io"
	"strconv"
	"time"
)

var sleepDelay = func(delay time.Duration) {
	time.Sleep(delay)
}

type lener interface {
	Len() int
}

func BuildContentLength(r *Request) {
	if slength := r.HTTPRequest.Header.Get("Content-Length"); slength != "" {
		length, _ := strconv.ParseInt(slength, 10, 64)
		r.HTTPRequest.ContentLength = length
		return
	}

	var length int64
	switch body := r.Body.(type) {
	case nil:
		length = 0
	case lener:
		length = int64(body.Len())
	case io.Seeker:
		cur, _ := body.Seek(0, 1)
		end, _ := body.Seek(0, 2)
		body.Seek(cur, 0) // make sure to seek back to original location
		length = end - cur
	default:
		panic("Cannot get length of body, must provide `ContentLength`")
	}

	r.HTTPRequest.ContentLength = length
	r.HTTPRequest.Header.Set("Content-Length", fmt.Sprintf("%d", length))
}

func UserAgentHandler(r *Request) {
	r.HTTPRequest.Header.Set("User-Agent", SDKName+"/"+SDKVersion)
}

func SendHandler(r *Request) {
	r.HTTPResponse, r.Error = r.Service.Config.HTTPClient.Do(r.HTTPRequest)
}

func ValidateResponseHandler(r *Request) {
	if r.HTTPResponse.StatusCode == 0 || r.HTTPResponse.StatusCode >= 400 {
		r.Error = &APIError{
			StatusCode: r.HTTPResponse.StatusCode,
			Code:       "UnknownError",
			Message:    "unknown error",
		}
	}
	r.Retryable = r.Service.ShouldRetry(r)
	r.RetryDelay = r.Service.RetryRules(r)
}

func AfterRetryHandler(r *Request) {
	if r.WillRetry() {
		sleepDelay(r.RetryDelay)

		r.RetryCount++
		r.Retryable = false
		r.Error = nil
	}
}

var (
	ErrMissingRegion   = fmt.Errorf("could not find region configuration.")
	ErrMissingEndpoint = fmt.Errorf("`Endpoint' configuration is required for this service.")
)

func ValidateEndpointHandler(r *Request) {
	if r.Service.Endpoint == "" {
		r.Error = ErrMissingEndpoint
	} else if r.Service.SigningRegion == "" && r.Service.Config.Region == "" {
		r.Error = ErrMissingRegion
	}
}
<commit_msg>Change order of errors in region validation check<commit_after>package aws

import (
	"fmt"
	"io"
	"strconv"
	"time"
)

var sleepDelay = func(delay time.Duration) {
	time.Sleep(delay)
}

type lener interface {
	Len() int
}

func BuildContentLength(r *Request) {
	if slength := r.HTTPRequest.Header.Get("Content-Length"); slength != "" {
		length, _ := strconv.ParseInt(slength, 10, 64)
		r.HTTPRequest.ContentLength = length
		return
	}

	var length int64
	switch body := r.Body.(type) {
	case nil:
		length = 0
	case lener:
		length = int64(body.Len())
	case io.Seeker:
		cur, _ := body.Seek(0, 1)
		end, _ := body.Seek(0, 2)
		body.Seek(cur, 0) // make sure to seek back to original location
		length = end - cur
	default:
		panic("Cannot get length of body, must provide `ContentLength`")
	}

	r.HTTPRequest.ContentLength = length
	r.HTTPRequest.Header.Set("Content-Length", fmt.Sprintf("%d", length))
}

func UserAgentHandler(r *Request) {
	r.HTTPRequest.Header.Set("User-Agent", SDKName+"/"+SDKVersion)
}

func SendHandler(r *Request) {
	r.HTTPResponse, r.Error = r.Service.Config.HTTPClient.Do(r.HTTPRequest)
}

func ValidateResponseHandler(r *Request) {
	if r.HTTPResponse.StatusCode == 0 || r.HTTPResponse.StatusCode >= 400 {
		r.Error = &APIError{
			StatusCode: r.HTTPResponse.StatusCode,
			Code:       "UnknownError",
			Message:    "unknown error",
		}
	}
	r.Retryable = r.Service.ShouldRetry(r)
	r.RetryDelay = r.Service.RetryRules(r)
}

func AfterRetryHandler(r *Request) {
	if r.WillRetry() {
		sleepDelay(r.RetryDelay)

		r.RetryCount++
		r.Retryable = false
		r.Error = nil
	}
}

var (
	ErrMissingRegion   = fmt.Errorf("could not find region configuration.")
	ErrMissingEndpoint = fmt.Errorf("`Endpoint' configuration is required for this service.")
)

func ValidateEndpointHandler(r *Request) {
	if r.Service.SigningRegion == "" && r.Service.Config.Region == "" {
		r.Error = ErrMissingRegion
	} else if r.Service.Endpoint == "" {
		r.Error = ErrMissingEndpoint
	}
}
<|endoftext|>


<commit_before>//  Copyright 2018 Istio Authors
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

package galley

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

	"google.golang.org/grpc"

	mcp "istio.io/api/mcp/v1alpha1"
	mcpclient "istio.io/istio/pkg/mcp/client"
	mcptestmon "istio.io/istio/pkg/mcp/testing/monitoring"
	tcontext "istio.io/istio/pkg/test/framework/api/context"
	"istio.io/istio/pkg/test/scopes"
	"istio.io/istio/pkg/test/util/retry"
)

type client struct {
	address string
	ctx     tcontext.Instance
}

func (c *client) waitForSnapshot(collection string, snapshot []map[string]interface{}) error {
	conn, err := c.dialGrpc()
	if err != nil {
		return err
	}
	defer func() { _ = conn.Close() }()

	collections := []string{collection}

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

	u := mcpclient.NewInMemoryUpdater()

	cl := mcp.NewAggregatedMeshConfigServiceClient(conn)
	mcpc := mcpclient.New(cl, collections, u, "", map[string]string{}, mcptestmon.NewInMemoryClientStatsContext())
	go mcpc.Run(ctx)

	var result *comparisonResult
	_, err = retry.Do(func() (interface{}, bool, error) {
		items := u.Get(collection)
		result, err = c.checkSnapshot(items, snapshot)
		if err != nil {
			return nil, false, err
		}
		err = result.generateError()
		return nil, err == nil, err
	}, retry.Delay(time.Millisecond), retry.Timeout(time.Second*5))

	return err
}

func (c *client) waitForStartup() (err error) {
	_, err = retry.Do(func() (interface{}, bool, error) {
		conn, err2 := c.dialGrpc()
		if err != nil {
			return nil, false, err2
		}
		_ = conn.Close()
		return nil, true, nil
	})

	return
}

func (c *client) checkSnapshot(actual []*mcpclient.Object, expected []map[string]interface{}) (*comparisonResult, error) {
	expectedMap := make(map[string]interface{})
	for _, e := range expected {
		name, err := extractName(e)
		if err != nil {
			return nil, err
		}
		expectedMap[name] = e
	}

	actualMap := make(map[string]interface{})
	for _, a := range actual {
		// Exclude ephemeral fields from comparison
		a.Metadata.CreateTime = nil
		a.Metadata.Version = ""

		b, err := json.Marshal(a)
		if err != nil {
			return nil, err
		}
		o := make(map[string]interface{})
		if err = json.Unmarshal(b, &o); err != nil {
			return nil, err
		}

		name := a.Metadata.Name
		actualMap[name] = o
	}

	var extraActual []string
	var missingExpected []string
	var conflicting []string

	for name, a := range actualMap {
		e, found := expectedMap[name]
		if !found {
			extraActual = append(extraActual, name)
			continue
		}

		if !reflect.DeepEqual(a, e) {
			conflicting = append(conflicting, name)
		}
	}

	for name := range expectedMap {
		_, found := actualMap[name]
		if !found {
			missingExpected = append(missingExpected, name)
			continue
		}
	}

	return &comparisonResult{
		expected:        expectedMap,
		actual:          actualMap,
		extraActual:     extraActual,
		missingExpected: missingExpected,
		conflicting:     conflicting,
	}, nil
}

func extractName(i map[string]interface{}) (string, error) {
	m, found := i["Metadata"]
	if !found {
		return "", fmt.Errorf("metadata section not found in resource")
	}

	meta, ok := m.(map[string]interface{})
	if !ok {
		return "", fmt.Errorf("metadata section is not a map")
	}

	n, found := meta["name"]
	if !found {
		return "", fmt.Errorf("metadata section does not contain name")
	}

	name, ok := n.(string)
	if !ok {
		return "", fmt.Errorf("name field is not a string")
	}

	return name, nil
}

func (c *client) dialGrpc() (*grpc.ClientConn, error) {

	addr := c.address
	if strings.HasPrefix(c.address, "tcp://") {
		addr = c.address[6:]
	}

	conn, err := grpc.Dial(addr, grpc.WithInsecure())
	if err != nil {

		return nil, err
	}
	scopes.Framework.Debug("connected to Galley pod through port forwarder")
	return conn, nil
}

// Close implements io.Closer.
func (c *client) Close() (err error) {

	return err
}
<commit_msg>Increase timeout (#11019)<commit_after>//  Copyright 2018 Istio Authors
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

package galley

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

	"google.golang.org/grpc"

	mcp "istio.io/api/mcp/v1alpha1"
	mcpclient "istio.io/istio/pkg/mcp/client"
	mcptestmon "istio.io/istio/pkg/mcp/testing/monitoring"
	tcontext "istio.io/istio/pkg/test/framework/api/context"
	"istio.io/istio/pkg/test/scopes"
	"istio.io/istio/pkg/test/util/retry"
)

type client struct {
	address string
	ctx     tcontext.Instance
}

func (c *client) waitForSnapshot(collection string, snapshot []map[string]interface{}) error {
	conn, err := c.dialGrpc()
	if err != nil {
		return err
	}
	defer func() { _ = conn.Close() }()

	collections := []string{collection}

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

	u := mcpclient.NewInMemoryUpdater()

	cl := mcp.NewAggregatedMeshConfigServiceClient(conn)
	mcpc := mcpclient.New(cl, collections, u, "", map[string]string{}, mcptestmon.NewInMemoryClientStatsContext())
	go mcpc.Run(ctx)

	var result *comparisonResult
	_, err = retry.Do(func() (interface{}, bool, error) {
		items := u.Get(collection)
		result, err = c.checkSnapshot(items, snapshot)
		if err != nil {
			return nil, false, err
		}
		err = result.generateError()
		return nil, err == nil, err
	}, retry.Delay(time.Millisecond), retry.Timeout(time.Second*20))

	return err
}

func (c *client) waitForStartup() (err error) {
	_, err = retry.Do(func() (interface{}, bool, error) {
		conn, err2 := c.dialGrpc()
		if err != nil {
			return nil, false, err2
		}
		_ = conn.Close()
		return nil, true, nil
	})

	return
}

func (c *client) checkSnapshot(actual []*mcpclient.Object, expected []map[string]interface{}) (*comparisonResult, error) {
	expectedMap := make(map[string]interface{})
	for _, e := range expected {
		name, err := extractName(e)
		if err != nil {
			return nil, err
		}
		expectedMap[name] = e
	}

	actualMap := make(map[string]interface{})
	for _, a := range actual {
		// Exclude ephemeral fields from comparison
		a.Metadata.CreateTime = nil
		a.Metadata.Version = ""

		b, err := json.Marshal(a)
		if err != nil {
			return nil, err
		}
		o := make(map[string]interface{})
		if err = json.Unmarshal(b, &o); err != nil {
			return nil, err
		}

		name := a.Metadata.Name
		actualMap[name] = o
	}

	var extraActual []string
	var missingExpected []string
	var conflicting []string

	for name, a := range actualMap {
		e, found := expectedMap[name]
		if !found {
			extraActual = append(extraActual, name)
			continue
		}

		if !reflect.DeepEqual(a, e) {
			conflicting = append(conflicting, name)
		}
	}

	for name := range expectedMap {
		_, found := actualMap[name]
		if !found {
			missingExpected = append(missingExpected, name)
			continue
		}
	}

	return &comparisonResult{
		expected:        expectedMap,
		actual:          actualMap,
		extraActual:     extraActual,
		missingExpected: missingExpected,
		conflicting:     conflicting,
	}, nil
}

func extractName(i map[string]interface{}) (string, error) {
	m, found := i["Metadata"]
	if !found {
		return "", fmt.Errorf("metadata section not found in resource")
	}

	meta, ok := m.(map[string]interface{})
	if !ok {
		return "", fmt.Errorf("metadata section is not a map")
	}

	n, found := meta["name"]
	if !found {
		return "", fmt.Errorf("metadata section does not contain name")
	}

	name, ok := n.(string)
	if !ok {
		return "", fmt.Errorf("name field is not a string")
	}

	return name, nil
}

func (c *client) dialGrpc() (*grpc.ClientConn, error) {

	addr := c.address
	if strings.HasPrefix(c.address, "tcp://") {
		addr = c.address[6:]
	}

	conn, err := grpc.Dial(addr, grpc.WithInsecure())
	if err != nil {

		return nil, err
	}
	scopes.Framework.Debug("connected to Galley pod through port forwarder")
	return conn, nil
}

// Close implements io.Closer.
func (c *client) Close() (err error) {

	return err
}
<|endoftext|>


<commit_before>package chroot

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

	. "github.com/polydawn/go-errcat"

	"go.polydawn.net/go-timeless-api"
	"go.polydawn.net/go-timeless-api/repeatr"
	"go.polydawn.net/go-timeless-api/rio"
	"go.polydawn.net/repeatr/executor/cradle"
	"go.polydawn.net/repeatr/executor/mixins"
	"go.polydawn.net/rio/fs"
	"go.polydawn.net/rio/fs/osfs"
	"go.polydawn.net/rio/stitch"
)

type Executor struct {
	workspaceFs   fs.FS             // A working dir per execution will be made in here.
	assemblerTool *stitch.Assembler // Contains: unpackTool, caching cfg, and placer tools.
	packTool      rio.PackFunc
}

func NewExecutor(
	workDir fs.AbsolutePath,
	unpackTool rio.UnpackFunc,
	packTool rio.PackFunc,
) (repeatr.RunFunc, error) {
	asm, err := stitch.NewAssembler(unpackTool)
	if err != nil {
		return nil, repeatr.ReboxRioError(err)
	}
	return Executor{
		osfs.New(workDir),
		asm,
		packTool,
	}.Run, nil
}

var _ repeatr.RunFunc = Executor{}.Run

func (cfg Executor) Run(
	ctx context.Context,
	formula api.Formula,
	formulaCtx api.FormulaContext,
	input repeatr.InputControl,
	mon repeatr.Monitor,
) (*api.RunRecord, error) {
	if mon.Chan != nil {
		defer close(mon.Chan)
	}

	// Workspace setup and params defaulting.
	formula = cradle.FormulaDefaults(formula)                    // Initialize formula default values.
	rr := api.RunRecord{}                                        // Start filling out record keeping!
	mixins.InitRunRecord(&rr, formula)                           // Includes picking a random guid for the job, which we use in all temp files.
	_, chrootFs, err := mixins.MakeWorkDirs(cfg.workspaceFs, rr) // Make work dirs. Including whole workspace dir and parents, if necessary.
	if err != nil {
		return nil, err
	}

	// Use standard filesystem setup/teardown, handing it our 'run' thunk
	//  to invoke while it's living.
	rr.Results, err = mixins.WithFilesystem(ctx,
		chrootFs, cfg.assemblerTool, cfg.packTool,
		formula, formulaCtx, mon,
		func(chrootFs fs.FS) (err error) {
			rr.ExitCode, err = run(ctx, formula.Action, chrootFs, input, mon)
			return
		},
	)
	return &rr, err
}

func run(
	ctx context.Context,
	action api.FormulaAction,
	chrootFs fs.FS,
	input repeatr.InputControl,
	mon repeatr.Monitor,
) (int, error) {
	// Check that action commands appear to be executable on this filesystem.
	if err := mixins.CheckFSReadyForExec(action, chrootFs); err != nil {
		return -1, err
	}

	// Configure the container.
	cmdName := action.Exec[0]
	cmd := exec.Command(cmdName, action.Exec[1:]...)
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Chroot: chrootFs.BasePath().String(),
		Credential: &syscall.Credential{
			Uid: uint32(*action.Userinfo.Uid),
			Gid: uint32(*action.Userinfo.Gid),
		},
	}
	cmd.Dir = string(action.Cwd)
	cmd.Env = envToSlice(action.Env)

	// Wire I/O.
	if input.Chan != nil {
		pipe, _ := cmd.StdinPipe()
		mixins.RunInputWriteForwarder(ctx, pipe, input.Chan)
	}
	proxy := mixins.NewOutputEventWriter(ctx, mon.Chan)
	cmd.Stdout = proxy
	cmd.Stderr = proxy

	// Invoke!
	return runCmd(cmd)
}

func runCmd(cmd *exec.Cmd) (int, error) {
	if err := cmd.Start(); err != nil {
		return -1, Errorf(repeatr.ErrExecutor, "executor failed to launch: %s", err)
	}
	err := cmd.Wait()
	if err == nil {
		return 0, nil
	}
	exitErr, ok := err.(*exec.ExitError)
	if !ok { // This is basically an "if stdlib isn't what we thought it is" error, so panic-worthy.
		panic(fmt.Errorf("unknown exit reason: %T %s", err, err))
	}
	waitStatus, ok := exitErr.ProcessState.Sys().(syscall.WaitStatus)
	if !ok { // This is basically a "if stdlib[...]" or OS portability issue, so also panic-able.
		panic(fmt.Errorf("unknown process state implementation %T", exitErr.ProcessState.Sys()))
	}
	if waitStatus.Exited() {
		return waitStatus.ExitStatus(), nil
	} else if waitStatus.Signaled() {
		// In bash, when a processs ends from a signal, the $? variable is set to 128+SIG.
		// We follow that same convention here.
		// So, a process terminated by ctrl-C returns 130.  A script that died to kill-9 returns 137.
		return int(waitStatus.Signal()) + 128, nil
	} else {
		return -1, Errorf(repeatr.ErrExecutor, "unknown process wait status (%#v)", waitStatus)
	}

}

func envToSlice(env map[string]string) []string {
	rv := make([]string, len(env))
	i := 0
	for k, v := range env {
		rv[i] = k + "=" + v
		i++
	}
	return rv
}
<commit_msg>whitespace police.<commit_after>package chroot

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

	. "github.com/polydawn/go-errcat"

	"go.polydawn.net/go-timeless-api"
	"go.polydawn.net/go-timeless-api/repeatr"
	"go.polydawn.net/go-timeless-api/rio"
	"go.polydawn.net/repeatr/executor/cradle"
	"go.polydawn.net/repeatr/executor/mixins"
	"go.polydawn.net/rio/fs"
	"go.polydawn.net/rio/fs/osfs"
	"go.polydawn.net/rio/stitch"
)

type Executor struct {
	workspaceFs   fs.FS             // A working dir per execution will be made in here.
	assemblerTool *stitch.Assembler // Contains: unpackTool, caching cfg, and placer tools.
	packTool      rio.PackFunc
}

func NewExecutor(
	workDir fs.AbsolutePath,
	unpackTool rio.UnpackFunc,
	packTool rio.PackFunc,
) (repeatr.RunFunc, error) {
	asm, err := stitch.NewAssembler(unpackTool)
	if err != nil {
		return nil, repeatr.ReboxRioError(err)
	}
	return Executor{
		osfs.New(workDir),
		asm,
		packTool,
	}.Run, nil
}

var _ repeatr.RunFunc = Executor{}.Run

func (cfg Executor) Run(
	ctx context.Context,
	formula api.Formula,
	formulaCtx api.FormulaContext,
	input repeatr.InputControl,
	mon repeatr.Monitor,
) (*api.RunRecord, error) {
	if mon.Chan != nil {
		defer close(mon.Chan)
	}

	// Workspace setup and params defaulting.
	formula = cradle.FormulaDefaults(formula)                    // Initialize formula default values.
	rr := api.RunRecord{}                                        // Start filling out record keeping!
	mixins.InitRunRecord(&rr, formula)                           // Includes picking a random guid for the job, which we use in all temp files.
	_, chrootFs, err := mixins.MakeWorkDirs(cfg.workspaceFs, rr) // Make work dirs. Including whole workspace dir and parents, if necessary.
	if err != nil {
		return nil, err
	}

	// Use standard filesystem setup/teardown, handing it our 'run' thunk
	//  to invoke while it's living.
	rr.Results, err = mixins.WithFilesystem(ctx,
		chrootFs, cfg.assemblerTool, cfg.packTool,
		formula, formulaCtx, mon,
		func(chrootFs fs.FS) (err error) {
			rr.ExitCode, err = run(ctx, formula.Action, chrootFs, input, mon)
			return
		},
	)
	return &rr, err
}

func run(
	ctx context.Context,
	action api.FormulaAction,
	chrootFs fs.FS,
	input repeatr.InputControl,
	mon repeatr.Monitor,
) (int, error) {
	// Check that action commands appear to be executable on this filesystem.
	if err := mixins.CheckFSReadyForExec(action, chrootFs); err != nil {
		return -1, err
	}

	// Configure the container.
	cmdName := action.Exec[0]
	cmd := exec.Command(cmdName, action.Exec[1:]...)
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Chroot: chrootFs.BasePath().String(),
		Credential: &syscall.Credential{
			Uid: uint32(*action.Userinfo.Uid),
			Gid: uint32(*action.Userinfo.Gid),
		},
	}
	cmd.Dir = string(action.Cwd)
	cmd.Env = envToSlice(action.Env)

	// Wire I/O.
	if input.Chan != nil {
		pipe, _ := cmd.StdinPipe()
		mixins.RunInputWriteForwarder(ctx, pipe, input.Chan)
	}
	proxy := mixins.NewOutputEventWriter(ctx, mon.Chan)
	cmd.Stdout = proxy
	cmd.Stderr = proxy

	// Invoke!
	return runCmd(cmd)
}

func runCmd(cmd *exec.Cmd) (int, error) {
	if err := cmd.Start(); err != nil {
		return -1, Errorf(repeatr.ErrExecutor, "executor failed to launch: %s", err)
	}
	err := cmd.Wait()
	if err == nil {
		return 0, nil
	}
	exitErr, ok := err.(*exec.ExitError)
	if !ok { // This is basically an "if stdlib isn't what we thought it is" error, so panic-worthy.
		panic(fmt.Errorf("unknown exit reason: %T %s", err, err))
	}
	waitStatus, ok := exitErr.ProcessState.Sys().(syscall.WaitStatus)
	if !ok { // This is basically a "if stdlib[...]" or OS portability issue, so also panic-able.
		panic(fmt.Errorf("unknown process state implementation %T", exitErr.ProcessState.Sys()))
	}
	if waitStatus.Exited() {
		return waitStatus.ExitStatus(), nil
	} else if waitStatus.Signaled() {
		// In bash, when a processs ends from a signal, the $? variable is set to 128+SIG.
		// We follow that same convention here.
		// So, a process terminated by ctrl-C returns 130.  A script that died to kill-9 returns 137.
		return int(waitStatus.Signal()) + 128, nil
	} else {
		return -1, Errorf(repeatr.ErrExecutor, "unknown process wait status (%#v)", waitStatus)
	}
}

func envToSlice(env map[string]string) []string {
	rv := make([]string, len(env))
	i := 0
	for k, v := range env {
		rv[i] = k + "=" + v
		i++
	}
	return rv
}
<|endoftext|>


<commit_before>package easyrss

import (
	"errors"
	"github.com/moovweb/gokogiri/xml"
	"strconv"
	"strings"
	"time"
)

type ItunesMeta struct {
	author   string
	subtitle string
	summary  string
	image    Image
	explicit string
	duration time.Duration
	keywords string
}

//Sets Appropriate Field Given Itunes Node
func setItunesMetaField(n xml.Node, i *ItunesMeta) {
	tag := n.Name()
	tagContent := n.Content()
	switch tag {
	case "subtitle":
		i.subtitle = tagContent
	case "author":
		i.author = tagContent
	case "summary":
		i.summary = tagContent
	case "explicit":
		i.explicit = tagContent
	case "keywords":
		i.keywords = tagContent
	case "duration":
		splitDur := strings.Split(tagContent, ":")
		if len(splitDur) != 3 { //Not H:M:S format
			return
		}
		hours, e := strconv.ParseInt(splitDur[0], 10, 8)
		if e != nil {
			return
		}
		minutes, e := strconv.ParseInt(splitDur[1], 10, 8)
		if e != nil {
			return
		}
		seconds, e := strconv.ParseInt(splitDur[2], 10, 8)
		if e != nil {
			return
		}
		i.duration = time.Duration(time.Duration(hours)*time.Hour + time.Duration(minutes)*time.Minute + time.Duration(seconds)*time.Second)
	case "image":
		if urlNode := n.Attribute("href"); urlNode != nil {
			i.image.url = urlNode.Value()
		}
	default:
		return
	}
}

//Whether or not this feed implements ItunesRSS Extensions
func (r *RSS) IsItunes() bool {
	return r.channel.isItunes
}

//Returns the Itunes "author" field for the channel. If the channel doesn't contain ITunes Extensions or hasn't populated the channel-wide Itunes "author" field, will return an empty string and an error
func (r *RSS) ItunesAuthor() (string, error) {
	if !r.channel.isItunes {
		return "", errors.New("Not an Itunes RSS Feed")
	}
	if r.channel.itunes.author == "" {
		return "", errors.New("Itunes author field not populated")
	}
	return r.channel.itunes.author, nil
}

//Returns the Itunes "author" field for the channel. If the channel doesn't contain ITunes Extensions or hasn't populated the channel-wide Itunes "subtitle" field, will return an empty string and an error
func (r *RSS) ItunesSubtitle() (string, error) {
	if !r.channel.isItunes {
		return "", errors.New("Not an Itunes RSS Feed")
	}
	if r.channel.itunes.subtitle == "" {
		return "", errors.New("Itunes subtitle field not populated")
	}
	return r.channel.itunes.subtitle, nil
}

//Returns the Itunes "summary" field for the channel. If the channel doesn't contain ITunes Extensions or hasn't populated the channel-wide Itunes "summary" field, will return an empty string and an error
func (r *RSS) ItunesSummary() (string, error) {
	if !r.channel.isItunes {
		return "", errors.New("Not an Itunes RSS Feed")
	}
	if r.channel.itunes.subtitle == "" {
		return "", errors.New("Itunes summary field not populated")
	}
	return r.channel.itunes.subtitle, nil
}

//Returns the Itunes "image" field for the channel. If the channel doesn't contain ITunes Extensions or hasn't populated the channel-wide Itunes "image" field, will return nil and an error.
func (r *RSS) ItunesImage() (*Image, error) {
	if !r.channel.isItunes {
		return nil, errors.New("Not an Itunes RSS Feed")
	}
	if r.channel.itunes.image.url == "" {
		return nil, errors.New("Itunes image fields not populated")
	}
	return &r.channel.itunes.image, nil
}

//Returns the Itunes "explicit" field for the channel. If the channel doesn't contain ITunes Extensions or hasn't populated the channel-wide Itunes "explicit" field, will return an empty string and an error func (r *RSS) ItunesExplicit() (string, error) {
func (r *RSS) ItunesExplicit() (string, error) {
	if !r.channel.isItunes {
		return "", errors.New("Not an Itunes RSS Feed")
	}
	if r.channel.itunes.explicit == "" {
		return "", errors.New("Itunes explicit field not populated")
	}
	return r.channel.itunes.explicit, nil
}

//Returns Itunes episode duration. If this information wasn't available or the item doesn't contain Itunes Extensions then we return nil and an error.
func (i Item) ItunesDuration() (*time.Duration, error) {
	if !i.isItunes {
		return nil, errors.New("Not an Itunes RSS Feed")
	}
	if int(i.itunes.duration) == 0 {
		return nil, errors.New("Itunes duration field missing")
	}
	return &i.itunes.duration, nil
}
<commit_msg>Add more Itunes fields<commit_after>package easyrss

import (
	"errors"
	"github.com/moovweb/gokogiri/xml"
	"strconv"
	"strings"
	"time"
)

type ItunesMeta struct {
	author   string
	subtitle string
	summary  string
	image    Image
	explicit string
	duration time.Duration
	keywords string
}

//Sets Appropriate Field Given Itunes Node
func setItunesMetaField(n xml.Node, i *ItunesMeta) {
	tag := n.Name()
	tagContent := n.Content()
	switch tag {
	case "subtitle":
		i.subtitle = tagContent
	case "author":
		i.author = tagContent
	case "summary":
		i.summary = tagContent
	case "explicit":
		i.explicit = tagContent
	case "keywords":
		i.keywords = tagContent
	case "duration":
		splitDur := strings.Split(tagContent, ":")
		if len(splitDur) != 3 { //Not H:M:S format
			return
		}
		hours, e := strconv.ParseInt(splitDur[0], 10, 8)
		if e != nil {
			return
		}
		minutes, e := strconv.ParseInt(splitDur[1], 10, 8)
		if e != nil {
			return
		}
		seconds, e := strconv.ParseInt(splitDur[2], 10, 8)
		if e != nil {
			return
		}
		i.duration = time.Duration(time.Duration(hours)*time.Hour + time.Duration(minutes)*time.Minute + time.Duration(seconds)*time.Second)
	case "image":
		if urlNode := n.Attribute("href"); urlNode != nil {
			i.image.url = urlNode.Value()
		}
	default:
		return
	}
}

//Whether or not this feed implements ItunesRSS Extensions
func (r *RSS) IsItunes() bool {
	return r.channel.isItunes
}

//Returns the Itunes "author" field for the channel. If the channel doesn't contain ITunes Extensions or hasn't populated the channel-wide Itunes "author" field, will return an empty string and an error
func (r *RSS) ItunesAuthor() (string, error) {
	if !r.channel.isItunes {
		return "", errors.New("Not an Itunes RSS Feed")
	}
	if r.channel.itunes.author == "" {
		return "", errors.New("Itunes author field not populated")
	}
	return r.channel.itunes.author, nil
}

//Returns the Itunes "author" field for the channel. If the channel doesn't contain ITunes Extensions or hasn't populated the channel-wide Itunes "subtitle" field, will return an empty string and an error
func (r *RSS) ItunesSubtitle() (string, error) {
	if !r.channel.isItunes {
		return "", errors.New("Not an Itunes RSS Feed")
	}
	if r.channel.itunes.subtitle == "" {
		return "", errors.New("Itunes subtitle field not populated")
	}
	return r.channel.itunes.subtitle, nil
}

//Returns the Itunes "summary" field for the channel. If the channel doesn't contain ITunes Extensions or hasn't populated the channel-wide Itunes "summary" field, will return an empty string and an error
func (r *RSS) ItunesSummary() (string, error) {
	if !r.channel.isItunes {
		return "", errors.New("Not an Itunes RSS Feed")
	}
	if r.channel.itunes.subtitle == "" {
		return "", errors.New("Itunes summary field not populated")
	}
	return r.channel.itunes.subtitle, nil
}

//Returns the Itunes "image" field for the channel. If the channel doesn't contain ITunes Extensions or hasn't populated the channel-wide Itunes "image" field, will return nil and an error.
func (r *RSS) ItunesImage() (*Image, error) {
	if !r.channel.isItunes {
		return nil, errors.New("Not an Itunes RSS Feed")
	}
	if r.channel.itunes.image.url == "" {
		return nil, errors.New("Itunes image fields not populated")
	}
	return &r.channel.itunes.image, nil
}

//Returns the Itunes "explicit" field for the channel. If the channel doesn't contain ITunes Extensions or hasn't populated the channel-wide Itunes "explicit" field, will return an empty string and an error func (r *RSS) ItunesExplicit() (string, error) {
func (r *RSS) ItunesExplicit() (string, error) {
	if !r.channel.isItunes {
		return "", errors.New("Not an Itunes RSS Feed")
	}
	if r.channel.itunes.explicit == "" {
		return "", errors.New("Itunes explicit field not populated")
	}
	return r.channel.itunes.explicit, nil
}

//Returns the Itunes "author" field for the item. If the item doesn't contain ITunes Extensions or hasn't populated the Itunes "author" field, will return an empty string and an error
func (i *Item) ItunesAuthor() (string, error) {
	if !i.isItunes {
		return "", errors.New("Not an Itunes RSS Feed")
	}
	if i.itunes.author == "" {
		return "", errors.New("Itunes author field not populated")
	}
	return i.itunes.author, nil
}

//Returns the Itunes "author" field for the item. If the item doesn't contain ITunes Extensions or hasn't populated the Itunes "subtitle" field, will return an empty string and an error
func (i *Item) ItunesSubtitle() (string, error) {
	if !i.isItunes {
		return "", errors.New("Not an Itunes RSS Feed")
	}
	if i.itunes.subtitle == "" {
		return "", errors.New("Itunes subtitle field not populated")
	}
	return i.itunes.subtitle, nil
}

//Returns the Itunes "summary" field for the item. If the item doesn't contain ITunes Extensions or hasn't populated the Itunes "summary" field, will return an empty string and an error
func (i *Item) ItunesSummary() (string, error) {
	if !i.isItunes {
		return "", errors.New("Not an Itunes RSS Feed")
	}
	if i.itunes.subtitle == "" {
		return "", errors.New("Itunes summary field not populated")
	}
	return i.itunes.subtitle, nil
}
//Returns Itunes episode duration. If this information wasn't available or the item doesn't contain Itunes Extensions then we return nil and an error.
func (i Item) ItunesDuration() (*time.Duration, error) {
	if !i.isItunes {
		return nil, errors.New("Not an Itunes RSS Feed")
	}
	if int(i.itunes.duration) == 0 {
		return nil, errors.New("Itunes duration field missing")
	}
	return &i.itunes.duration, nil
}

//Returns the Itunes "image" field for the item. If the item doesn't contain ITunes Extensions or hasn't populated the Itunes "image" field, will return nil and an error.
func (i *Item) ItunesImage() (*Image, error) {
	if !i.isItunes {
		return nil, errors.New("Not an Itunes RSS Feed")
	}
	if i.itunes.image.url == "" {
		return nil, errors.New("Itunes image fields not populated")
	}
	return &i.itunes.image, nil
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/guzzlerio/corcel/serialisation/yaml"
	"github.com/guzzlerio/corcel/statistics"
	"github.com/guzzlerio/corcel/utils"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("ExecutionPlan Assertions", func() {

	Context("ExactAssertion", func() {

		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", "talula").Build()).
				WithAssertion(planBuilder.ExactAssertion("value:1", "talula"))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})

		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 2).Build()).
				WithAssertion(planBuilder.ExactAssertion("value:1", 1))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(1)))
		})

	})

	Context("EmptyAssertion", func() {

		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", "").Build()).
				WithAssertion(planBuilder.EmptyAssertion("value:1"))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})

		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", "1").Build()).
				WithAssertion(planBuilder.EmptyAssertion("value:1"))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(1)))
		})

	})

	Context("GreaterThanAssertion", func() {

		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 5).Build()).
				WithAssertion(planBuilder.GreaterThanAssertion("value:1", 2))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})

		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 2).Build()).
				WithAssertion(planBuilder.GreaterThanAssertion("value:1", 5))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(1)))
		})

	})

	Context("GreaterThanOrEqualAssertion", func() {

		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 5).Build()).
				WithAssertion(planBuilder.GreaterThanOrEqualAssertion("value:1", 5))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})

		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 2).Build()).
				WithAssertion(planBuilder.GreaterThanOrEqualAssertion("value:1", 5))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(1)))
		})

	})

	Context("LessThanAssertion", func() {

		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 3).Build()).
				WithAssertion(planBuilder.LessThanAssertion("value:1", 5))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})

		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 5).Build()).
				WithAssertion(planBuilder.LessThanAssertion("value:1", 3))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(1)))
		})

	})

	Context("LessThanOrEqualAssertion", func() {

		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 5).Build()).
				WithAssertion(planBuilder.LessThanOrEqualAssertion("value:1", 5))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})

		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 5).Build()).
				WithAssertion(planBuilder.LessThanOrEqualAssertion("value:1", 4))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(1)))
		})

	})

	Context("NotEmptyAssertion", func() {

		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 5).Build()).
				WithAssertion(planBuilder.NotEmptyAssertion("value:1"))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})

		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:2", 5).Build()).
				WithAssertion(planBuilder.NotEmptyAssertion("value:1"))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(1)))
		})

	})

	Context("NotEqualAssertion", func() {

		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 5).Build()).
				WithAssertion(planBuilder.NotEqualAssertion("value:1", 6))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})

		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 6).Build()).
				WithAssertion(planBuilder.NotEqualAssertion("value:1", 6))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(1)))
		})

	})
})
<commit_msg>Replaced the ExecutionPlan Assertion tests with inprocess ones<commit_after>package main

import (
	"github.com/guzzlerio/corcel/serialisation/yaml"
	"github.com/guzzlerio/corcel/statistics"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("ExecutionPlan Assertions", func() {

	Context("ExactAssertion", func() {

		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", "talula").Build()).
				WithAssertion(planBuilder.ExactAssertion("value:1", "talula"))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})

		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 2).Build()).
				WithAssertion(planBuilder.ExactAssertion("value:1", 1))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(1)))
		})

	})

	Context("EmptyAssertion", func() {

		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", "").Build()).
				WithAssertion(planBuilder.EmptyAssertion("value:1"))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})

		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", "1").Build()).
				WithAssertion(planBuilder.EmptyAssertion("value:1"))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(1)))
		})

	})

	Context("GreaterThanAssertion", func() {

		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 5).Build()).
				WithAssertion(planBuilder.GreaterThanAssertion("value:1", 2))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})

		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 2).Build()).
				WithAssertion(planBuilder.GreaterThanAssertion("value:1", 5))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(1)))
		})

	})

	Context("GreaterThanOrEqualAssertion", func() {

		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 5).Build()).
				WithAssertion(planBuilder.GreaterThanOrEqualAssertion("value:1", 5))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})

		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 2).Build()).
				WithAssertion(planBuilder.GreaterThanOrEqualAssertion("value:1", 5))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(1)))
		})

	})

	Context("LessThanAssertion", func() {

		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 3).Build()).
				WithAssertion(planBuilder.LessThanAssertion("value:1", 5))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})

		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 5).Build()).
				WithAssertion(planBuilder.LessThanAssertion("value:1", 3))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(1)))
		})

	})

	Context("LessThanOrEqualAssertion", func() {

		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 5).Build()).
				WithAssertion(planBuilder.LessThanOrEqualAssertion("value:1", 5))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})

		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 5).Build()).
				WithAssertion(planBuilder.LessThanOrEqualAssertion("value:1", 4))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(1)))
		})

	})

	Context("NotEmptyAssertion", func() {

		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 5).Build()).
				WithAssertion(planBuilder.NotEmptyAssertion("value:1"))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})

		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:2", 5).Build()).
				WithAssertion(planBuilder.NotEmptyAssertion("value:1"))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(1)))
		})

	})

	Context("NotEqualAssertion", func() {

		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 5).Build()).
				WithAssertion(planBuilder.NotEqualAssertion("value:1", 6))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})

		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("value:1", 6).Build()).
				WithAssertion(planBuilder.NotEqualAssertion("value:1", 6))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(1)))
		})

	})
})
<|endoftext|>


<commit_before>package main

import (
        chatwork "github.com/yoppi/go-chatwork"
        "fmt"
)

var apiKey = `api-key`

func main() {
	// GET
        c := chatwork.NewClient(apiKey)
        fmt.Print(c.Rooms())
        fmt.Print(c.Room("room-id"))
        fmt.Print(c.RoomMembers("room-id"))
        fmt.Print(c.RoomMessages("room-id"))
        fmt.Print(c.RoomMessage("room-id", "message-id"))
        fmt.Print(c.RoomTasks("room-id"))
        fmt.Print(c.RoomTask("room-id", "task-id"))
        fmt.Print(c.RoomFiles("room-id", map[string]string{}))
        fmt.Print(c.RoomFile("room-id", "file-id"))

	// POST
	fmt.Println(c.CreateRoom(map[string]string {
		"name": "Test Room",
		"members_admin_ids": `user-id`,
		"description": "テスト",
	}))
}
<commit_msg>Fix example code<commit_after>package main

import (
        chatwork "github.com/yoppi/go-chatwork"
	"flag"
        "fmt"
)

var apiKey string

func init() {
	flag.StringVar(&apiKey, "key", "", "Chatwork API key")
	flag.Parse()
}

func main() {
	// GET
        c := chatwork.NewClient(apiKey)
        fmt.Printf("%+v\n", c.Rooms())
        fmt.Printf("%+v\n", c.Room(`room-id`))
        fmt.Printf("%+v\n", c.RoomMembers(`room-id`))
        fmt.Print(c.RoomMessages(`room-id`))
        fmt.Printf("%+v\n", c.RoomMessage(`room-id`, `message-id`))
        fmt.Printf("%+v\n", c.RoomTasks(`room-id`))
        fmt.Printf("%+v\n", c.RoomTask(`room-id`, `task-id`))
        fmt.Printf("%+v\n", c.RoomFiles(`room-id`, map[string]string{}))
        fmt.Printf("%+v\n", c.RoomFile(`room-id`, `file-id`))

	// POST
	c.CreateRoom(map[string]string {
		"name": "Test Room",
		"members_admin_ids": `user-id`,
		"description": "テスト",
	})

	// PUT
	c.UpdateRoom(`room-id`, map[string]string {
		"name": "テストルーム",
		"description": "Update description",
	})
	c.UpdateRoomMembers(`room-id`, map[string]string {
		"members_admin_ids": `user-id`,
		"members_member_ids": `user-id`,
		"members_readonly_ids": `user-id`,
	})

	// DELETE
	c.DeleteRoom(`room-id`, map[string]string {
		"action_type": "delete",
	})
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"

	"github.com/valyala/fasthttp"
	"github.com/valyala/fasthttp/reuseport"
)

var (
	addr = flag.String("addr", ":8080", "TCP address to listen to")
)

var body = []byte("OK")

func main() {
	flag.Parse()

	ln, err := reuseport.Listen("tcp4", *addr)
	if err != nil {
		log.Fatal(err)
	}

	if err := fasthttp.Serve(ln, requestHandler); err != nil {
		log.Fatalf("Error in ListenAndServe: %s", err)
	}
}

func requestHandler(ctx *fasthttp.RequestCtx) {
	_, err := ctx.Write(body)
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>void server returns "no content" header<commit_after>package main

import (
	"flag"
	"log"

	"github.com/valyala/fasthttp"
	"github.com/valyala/fasthttp/reuseport"
)

var (
	addr = flag.String("addr", ":8080", "TCP address to listen to")
)

var body = []byte("\n")

func main() {
	flag.Parse()

	ln, err := reuseport.Listen("tcp4", *addr)
	if err != nil {
		log.Fatal(err)
	}

	if err := fasthttp.Serve(ln, defaultRequestHandler); err != nil {
		log.Fatalf("Error in ListenAndServe: %s", err)
	}
}

func defaultRequestHandler(ctx *fasthttp.RequestCtx) {
	ctx.SetStatusCode(fasthttp.StatusNoContent)
}
<|endoftext|>


<commit_before>package build

import (
	"fmt"
	"neon/util"
	"os"
)

// Target is a structure for a target
type Target struct {
	Build   *Build
	Name    string
	Doc     string
	Depends []string
	Steps   Steps
}

// NewTarget makes a new target:
// - build: the build of the target
// - name: the name of the target
// - object: the body of the target as an interface
// Returns:
// - a pointer to the built target
// - an error if something went wrong
func NewTarget(build *Build, name string, object util.Object) (*Target, error) {
	target := &Target{
		Build: build,
		Name:  name,
	}
	err := object.CheckFields([]string{"doc", "depends", "steps"})
	if err != nil {
		return nil, err
	}
	if err := ParseTargetDoc(object, target); err != nil {
		return nil, err
	}
	if err := ParseTargetDepends(object, target); err != nil {
		return nil, err
	}
	if err := ParseTargetSteps(object, target); err != nil {
		return nil, err
	}
	return target, nil
}

// ParseTargetDoc parses documentation of the target:
// - object: body of the target as an interface
// - target: the target to document
// Return: an error if something went wrong
func ParseTargetDoc(object util.Object, target *Target) error {
	if object.HasField("doc") {
		doc, err := object.GetString("doc")
		if err != nil {
			return fmt.Errorf("doc field in target '%s' must be a string", target.Name)
		}
		target.Doc = doc
	}
	return nil
}

// ParseTargetDepends parses target dependencies:
// - object: the target body as an interface
// - target: the target being parsed
// Return: an error if something went wrong
func ParseTargetDepends(object util.Object, target *Target) error {
	if object.HasField("depends") {
		depends, err := object.GetListStringsOrString("depends")
		if err != nil {
			return fmt.Errorf("depends field must be a string or list of strings")
		}
		target.Depends = depends
	}
	return nil
}

// ParseTargetSteps parses steps of a target:
// - object: the target body as an interface
// - target: the target being parsed
// Return: an error if something went wrong
func ParseTargetSteps(object util.Object, target *Target) error {
	if object.HasField("steps") {
		list, err := object.GetList("steps")
		if err != nil {
			return fmt.Errorf("parsig target '%s': steps must be a list", target.Name)
		}
		var steps []Step
		for index, object := range list {
			step, err := NewStep(object)
			if err != nil {
				return fmt.Errorf("in step %d: %v", index+1, err)
			}
			steps = append(steps, step)
		}
		target.Steps = steps
	}
	return nil
}

// Run target in given context:
// - context: the context of the build
// Return: an error if something went wrong
func (target *Target) Run(context *Context) error {
	for _, name := range target.Depends {
		if !context.Stack.Contains(name) {
			err := target.Build.Root.RunTarget(context, name)
			if err != nil {
				return err
			}
		}
	}
	err := context.Stack.Push(target)
	if err != nil {
		return err
	}
	Title(target.Name)
	if target.Build.Template {
		err = os.Chdir(target.Build.Here)
		if err != nil {
			return fmt.Errorf("changing to current directory '%s'", target.Build.Dir)
		}
	} else {
		err = os.Chdir(target.Build.Dir)
		if err != nil {
			return fmt.Errorf("changing to build directory '%s'", target.Build.Dir)
		}
	}
	err = target.Steps.Run(context)
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>If optimization<commit_after>package build

import (
	"fmt"
	"neon/util"
	"os"
)

// Target is a structure for a target
type Target struct {
	Build   *Build
	Name    string
	Doc     string
	Depends []string
	Steps   Steps
}

// NewTarget makes a new target:
// - build: the build of the target
// - name: the name of the target
// - object: the body of the target as an interface
// Returns:
// - a pointer to the built target
// - an error if something went wrong
func NewTarget(build *Build, name string, object util.Object) (*Target, error) {
	target := &Target{
		Build: build,
		Name:  name,
	}
	if err := object.CheckFields([]string{"doc", "depends", "steps"}); err != nil {
		return nil, err
	}
	if err := ParseTargetDoc(object, target); err != nil {
		return nil, err
	}
	if err := ParseTargetDepends(object, target); err != nil {
		return nil, err
	}
	if err := ParseTargetSteps(object, target); err != nil {
		return nil, err
	}
	return target, nil
}

// ParseTargetDoc parses documentation of the target:
// - object: body of the target as an interface
// - target: the target to document
// Return: an error if something went wrong
func ParseTargetDoc(object util.Object, target *Target) error {
	if object.HasField("doc") {
		doc, err := object.GetString("doc")
		if err != nil {
			return fmt.Errorf("doc field in target '%s' must be a string", target.Name)
		}
		target.Doc = doc
	}
	return nil
}

// ParseTargetDepends parses target dependencies:
// - object: the target body as an interface
// - target: the target being parsed
// Return: an error if something went wrong
func ParseTargetDepends(object util.Object, target *Target) error {
	if object.HasField("depends") {
		depends, err := object.GetListStringsOrString("depends")
		if err != nil {
			return fmt.Errorf("depends field must be a string or list of strings")
		}
		target.Depends = depends
	}
	return nil
}

// ParseTargetSteps parses steps of a target:
// - object: the target body as an interface
// - target: the target being parsed
// Return: an error if something went wrong
func ParseTargetSteps(object util.Object, target *Target) error {
	if object.HasField("steps") {
		list, err := object.GetList("steps")
		if err != nil {
			return fmt.Errorf("parsig target '%s': steps must be a list", target.Name)
		}
		var steps []Step
		for index, object := range list {
			step, err := NewStep(object)
			if err != nil {
				return fmt.Errorf("in step %d: %v", index+1, err)
			}
			steps = append(steps, step)
		}
		target.Steps = steps
	}
	return nil
}

// Run target in given context:
// - context: the context of the build
// Return: an error if something went wrong
func (target *Target) Run(context *Context) error {
	for _, name := range target.Depends {
		if !context.Stack.Contains(name) {
			if err := target.Build.Root.RunTarget(context, name); err != nil {
				return err
			}
		}
	}
	if err := context.Stack.Push(target); err != nil {
		return err
	}
	Title(target.Name)
	if target.Build.Template {
		if err := os.Chdir(target.Build.Here); err != nil {
			return fmt.Errorf("changing to current directory '%s'", target.Build.Dir)
		}
	} else {
		if err := os.Chdir(target.Build.Dir); err != nil {
			return fmt.Errorf("changing to build directory '%s'", target.Build.Dir)
		}
	}
	if err := target.Steps.Run(context); err != nil {
		return err
	}
	return nil
}
<|endoftext|>