<commit_before>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://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.

// Code generated by gapic-generator. DO NOT EDIT.

package containeranalysis

import (
	"context"
	"fmt"
	"net/url"

	grafeas "cloud.google.com/go/grafeas/apiv1"
	gax "github.com/googleapis/gax-go/v2"
	"google.golang.org/api/option"
	gtransport "google.golang.org/api/transport/grpc"
	containeranalysispb "google.golang.org/genproto/googleapis/devtools/containeranalysis/v1"
	iampb "google.golang.org/genproto/googleapis/iam/v1"
	"google.golang.org/grpc"
	"google.golang.org/grpc/metadata"
)

// CallOptions contains the retry settings for each method of Client.
type CallOptions struct {
	SetIamPolicy       []gax.CallOption
	GetIamPolicy       []gax.CallOption
	TestIamPermissions []gax.CallOption
}

func defaultClientOptions() []option.ClientOption {
	return []option.ClientOption{
		option.WithEndpoint("containeranalysis.googleapis.com:443"),
		option.WithScopes(DefaultAuthScopes()...),
	}
}

func defaultCallOptions() *CallOptions {
	retry := map[[2]string][]gax.CallOption{}
	return &CallOptions{
		SetIamPolicy:       retry[[2]string{"default", "non_idempotent"}],
		GetIamPolicy:       retry[[2]string{"default", "non_idempotent"}],
		TestIamPermissions: retry[[2]string{"default", "non_idempotent"}],
	}
}

// Client is a client for interacting with Container Analysis API.
//
// Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls.
type Client struct {
	// The connection to the service.
	connPool gtransport.ConnPool

	// The gRPC API client.
	client containeranalysispb.ContainerAnalysisClient

	// A pre-crearted grafeas client.
	grafeasClient *grafeas.Client

	// The call options for this service.
	CallOptions *CallOptions

	// The x-goog-* metadata to be sent with each request.
	xGoogMetadata metadata.MD
}

// NewClient creates a new container analysis client.
//
// Retrieves analysis results of Cloud components such as Docker container
// images. The Container Analysis API is an implementation of the
// Grafeas (at https://grafeas.io) API.
//
// Analysis results are stored as a series of occurrences. An Occurrence
// contains information about a specific analysis instance on a resource. An
// occurrence refers to a Note. A note contains details describing the
// analysis and is generally stored in a separate project, called a Provider.
// Multiple occurrences can refer to the same note.
//
// For example, an SSL vulnerability could affect multiple images. In this case,
// there would be one note for the vulnerability and an occurrence for each
// image with the vulnerability referring to that note.
func NewClient(ctx context.Context, opts ...option.ClientOption) (*Client, error) {
	connPool, err := gtransport.DialPool(ctx, append(defaultClientOptions(), opts...)...)
	if err != nil {
		return nil, err
	}
	gc, err := grafeas.NewClient(ctx, append(defaultClientOptions(), opts...)...)
	if err != nil {
		return nil, err
	}
	c := &Client{
		connPool:    connPool,
		CallOptions: defaultCallOptions(),

		client:        containeranalysispb.NewContainerAnalysisClient(connPool),
		grafeasClient: gc,
	}
	c.setGoogleClientInfo()
	return c, nil
}

// GetGrafeasClient returns a grafeas client connected to containeranalysis.
//
// Calling Close on either the grafeas or containeranalysis client will close
// the shared connection in both.
func (c *Client) GetGrafeasClient() *grafeas.Client {
	return c.grafeasClient
}

// Connection returns the client's connection to the API service.
func (c *Client) Connection() *grpc.ClientConn {
	return c.connPool.Conn()
}

// Close closes the connection to the API service. The user should invoke this when
// the client is no longer required.
func (c *Client) Close() error {
	return c.connPool.Close()
}

// setGoogleClientInfo sets the name and version of the application in
// the `x-goog-api-client` header passed on each request. Intended for
// use by Google-written clients.
func (c *Client) setGoogleClientInfo(keyval ...string) {
	kv := append([]string{"gl-go", versionGo()}, keyval...)
	kv = append(kv, "gapic", versionClient, "gax", gax.Version, "grpc", grpc.Version)
	c.xGoogMetadata = metadata.Pairs("x-goog-api-client", gax.XGoogHeader(kv...))
}

// SetIamPolicy sets the access control policy on the specified note or occurrence.
// Requires containeranalysis.notes.setIamPolicy or
// containeranalysis.occurrences.setIamPolicy permission if the resource is
// a note or an occurrence, respectively.
//
// The resource takes the format projects/[PROJECT_ID]/notes/[NOTE_ID] for
// notes and projects/[PROJECT_ID]/occurrences/[OCCURRENCE_ID] for
// occurrences.
func (c *Client) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) {
	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource())))
	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
	opts = append(c.CallOptions.SetIamPolicy[0:len(c.CallOptions.SetIamPolicy):len(c.CallOptions.SetIamPolicy)], opts...)
	var resp *iampb.Policy
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.client.SetIamPolicy(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

// GetIamPolicy gets the access control policy for a note or an occurrence resource.
// Requires containeranalysis.notes.setIamPolicy or
// containeranalysis.occurrences.setIamPolicy permission if the resource is
// a note or occurrence, respectively.
//
// The resource takes the format projects/[PROJECT_ID]/notes/[NOTE_ID] for
// notes and projects/[PROJECT_ID]/occurrences/[OCCURRENCE_ID] for
// occurrences.
func (c *Client) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) {
	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource())))
	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
	opts = append(c.CallOptions.GetIamPolicy[0:len(c.CallOptions.GetIamPolicy):len(c.CallOptions.GetIamPolicy)], opts...)
	var resp *iampb.Policy
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.client.GetIamPolicy(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

// TestIamPermissions returns the permissions that a caller has on the specified note or
// occurrence. Requires list permission on the project (for example,
// containeranalysis.notes.list).
//
// The resource takes the format projects/[PROJECT_ID]/notes/[NOTE_ID] for
// notes and projects/[PROJECT_ID]/occurrences/[OCCURRENCE_ID] for
// occurrences.
func (c *Client) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) {
	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource())))
	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
	opts = append(c.CallOptions.TestIamPermissions[0:len(c.CallOptions.TestIamPermissions):len(c.CallOptions.TestIamPermissions)], opts...)
	var resp *iampb.TestIamPermissionsResponse
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.client.TestIamPermissions(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}
<commit_msg>fix(containeranalysis): fix docs and closing of client. (#5220)<commit_after>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://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.

// Code generated by gapic-generator. DO NOT EDIT.

package containeranalysis

import (
	"context"
	"fmt"
	"net/url"

	grafeas "cloud.google.com/go/grafeas/apiv1"
	gax "github.com/googleapis/gax-go/v2"
	"google.golang.org/api/option"
	gtransport "google.golang.org/api/transport/grpc"
	containeranalysispb "google.golang.org/genproto/googleapis/devtools/containeranalysis/v1"
	iampb "google.golang.org/genproto/googleapis/iam/v1"
	"google.golang.org/grpc"
	"google.golang.org/grpc/metadata"
)

// CallOptions contains the retry settings for each method of Client.
type CallOptions struct {
	SetIamPolicy       []gax.CallOption
	GetIamPolicy       []gax.CallOption
	TestIamPermissions []gax.CallOption
}

func defaultClientOptions() []option.ClientOption {
	return []option.ClientOption{
		option.WithEndpoint("containeranalysis.googleapis.com:443"),
		option.WithScopes(DefaultAuthScopes()...),
	}
}

func defaultCallOptions() *CallOptions {
	retry := map[[2]string][]gax.CallOption{}
	return &CallOptions{
		SetIamPolicy:       retry[[2]string{"default", "non_idempotent"}],
		GetIamPolicy:       retry[[2]string{"default", "non_idempotent"}],
		TestIamPermissions: retry[[2]string{"default", "non_idempotent"}],
	}
}

// Client is a client for interacting with Container Analysis API.
//
// Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls.
type Client struct {
	// The connection to the service.
	connPool gtransport.ConnPool

	// The gRPC API client.
	client containeranalysispb.ContainerAnalysisClient

	// A pre-crearted grafeas client.
	grafeasClient *grafeas.Client

	// The call options for this service.
	CallOptions *CallOptions

	// The x-goog-* metadata to be sent with each request.
	xGoogMetadata metadata.MD
}

// NewClient creates a new container analysis client.
//
// Retrieves analysis results of Cloud components such as Docker container
// images. The Container Analysis API is an implementation of the
// Grafeas (at https://grafeas.io) API.
//
// Analysis results are stored as a series of occurrences. An Occurrence
// contains information about a specific analysis instance on a resource. An
// occurrence refers to a Note. A note contains details describing the
// analysis and is generally stored in a separate project, called a Provider.
// Multiple occurrences can refer to the same note.
//
// For example, an SSL vulnerability could affect multiple images. In this case,
// there would be one note for the vulnerability and an occurrence for each
// image with the vulnerability referring to that note.
func NewClient(ctx context.Context, opts ...option.ClientOption) (*Client, error) {
	connPool, err := gtransport.DialPool(ctx, append(defaultClientOptions(), opts...)...)
	if err != nil {
		return nil, err
	}
	gc, err := grafeas.NewClient(ctx, append(defaultClientOptions(), opts...)...)
	if err != nil {
		return nil, err
	}
	c := &Client{
		connPool:    connPool,
		CallOptions: defaultCallOptions(),

		client:        containeranalysispb.NewContainerAnalysisClient(connPool),
		grafeasClient: gc,
	}
	c.setGoogleClientInfo()
	return c, nil
}

// GetGrafeasClient returns a grafeas client connected to containeranalysis.
func (c *Client) GetGrafeasClient() *grafeas.Client {
	return c.grafeasClient
}

// Connection returns the client's connection to the API service.
func (c *Client) Connection() *grpc.ClientConn {
	return c.connPool.Conn()
}

// Close closes the connection to the API service. The user should invoke this when
// the client is no longer required.
//
// Calling Close will also close the underlying grafeas client.
func (c *Client) Close() error {
	c.grafeasClient.Close()
	return c.connPool.Close()
}

// setGoogleClientInfo sets the name and version of the application in
// the `x-goog-api-client` header passed on each request. Intended for
// use by Google-written clients.
func (c *Client) setGoogleClientInfo(keyval ...string) {
	kv := append([]string{"gl-go", versionGo()}, keyval...)
	kv = append(kv, "gapic", versionClient, "gax", gax.Version, "grpc", grpc.Version)
	c.xGoogMetadata = metadata.Pairs("x-goog-api-client", gax.XGoogHeader(kv...))
}

// SetIamPolicy sets the access control policy on the specified note or occurrence.
// Requires containeranalysis.notes.setIamPolicy or
// containeranalysis.occurrences.setIamPolicy permission if the resource is
// a note or an occurrence, respectively.
//
// The resource takes the format projects/[PROJECT_ID]/notes/[NOTE_ID] for
// notes and projects/[PROJECT_ID]/occurrences/[OCCURRENCE_ID] for
// occurrences.
func (c *Client) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) {
	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource())))
	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
	opts = append(c.CallOptions.SetIamPolicy[0:len(c.CallOptions.SetIamPolicy):len(c.CallOptions.SetIamPolicy)], opts...)
	var resp *iampb.Policy
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.client.SetIamPolicy(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

// GetIamPolicy gets the access control policy for a note or an occurrence resource.
// Requires containeranalysis.notes.setIamPolicy or
// containeranalysis.occurrences.setIamPolicy permission if the resource is
// a note or occurrence, respectively.
//
// The resource takes the format projects/[PROJECT_ID]/notes/[NOTE_ID] for
// notes and projects/[PROJECT_ID]/occurrences/[OCCURRENCE_ID] for
// occurrences.
func (c *Client) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest, opts ...gax.CallOption) (*iampb.Policy, error) {
	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource())))
	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
	opts = append(c.CallOptions.GetIamPolicy[0:len(c.CallOptions.GetIamPolicy):len(c.CallOptions.GetIamPolicy)], opts...)
	var resp *iampb.Policy
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.client.GetIamPolicy(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

// TestIamPermissions returns the permissions that a caller has on the specified note or
// occurrence. Requires list permission on the project (for example,
// containeranalysis.notes.list).
//
// The resource takes the format projects/[PROJECT_ID]/notes/[NOTE_ID] for
// notes and projects/[PROJECT_ID]/occurrences/[OCCURRENCE_ID] for
// occurrences.
func (c *Client) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest, opts ...gax.CallOption) (*iampb.TestIamPermissionsResponse, error) {
	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "resource", url.QueryEscape(req.GetResource())))
	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
	opts = append(c.CallOptions.TestIamPermissions[0:len(c.CallOptions.TestIamPermissions):len(c.CallOptions.TestIamPermissions)], opts...)
	var resp *iampb.TestIamPermissionsResponse
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.client.TestIamPermissions(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}
<|endoftext|>


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

/*
Package template (html/template) is a specialization of package text/template
that automates the construction of HTML output that is safe against code
injection.

Introduction

This package wraps package template so you can use the standard template API
to parse and execute templates.

    set, err := new(template.Set).Parse(...)
    // Error checking elided
    err = set.Execute(out, "Foo", data)

If successful, set will now be injection-safe. Otherwise, err is an error
defined in the docs for ErrorCode.

HTML templates treat data values as plain text which should be encoded so they
can be safely embedded in an HTML document. The escaping is contextual, so
actions can appear within JavaScript, CSS, and URI contexts.

The security model used by this package assumes that template authors are
trusted, while Execute's data parameter is not. More details are provided below.

Example

    import "text/template"
    ...
    t, err := (&template.Set{}).Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
    err = t.Execute(out, "T", "")

produces

    Hello, !

but with contextual autoescaping,

    import "html/template"
    ...
    t, err := (&template.Set{}).Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
    err = t.Execute(out, "T", "")

produces safe, escaped HTML output

    Hello, <script>alert('you have been pwned')</script>!

Contexts

This package understands HTML, CSS, JavaScript, and URIs. It adds sanitizing
functions to each simple action pipeline, so given the excerpt

  {{.}}

At parse time each {{.}} is overwritten to add escaping functions as necessary,
in this case,

  {{. | html}}

Errors

See the documentation of ErrorCode for details.

A fuller picture

The rest of this package comment may be skipped on first reading; it includes
details necessary to understand escaping contexts and error messages. Most users
will not need to understand these details.

Contexts

Assuming {{.}} is `O'Reilly: How are <i>you</i>?`, the table below shows
how {{.}} appears when used in the context to the left.

Context                          {{.}} After
{{.}}                            O'Reilly: How are <i>you</i>?
                O'Reilly: How are you?
                O'Reilly: How are %3ci%3eyou%3c/i%3e?
              O'Reilly%3a%20How%20are%3ci%3e...%3f
             O\x27Reilly: How are \x3ci\x3eyou...?
               "O\x27Reilly: How are \x3ci\x3eyou...?"
     O\x27Reilly: How are \x3ci\x3eyou...\x3f

If used in an unsafe context, then the value might be filtered out:

Context                          {{.}} After
                 #ZgotmplZ

since "O'Reilly:" is not an allowed protocol like "http:".

If {{.}} is the innocuous word, `left`, then it can appear more widely,

Context                              {{.}} After
{{.}}                                left
                    left
                     left
                    left
                left
        left
             left
       left
  left
   left

Non-string values can be used in JavaScript contexts.
If {{.}} is

  []struct{A,B string}{ "foo", "bar" }

in the escaped template

then the template output is

See package json to understand how non-string content is marshalled for
embedding in JavaScript contexts.

Typed Strings

By default, this package assumes that all pipelines produce a plain text string.
It adds escaping pipeline stages necessary to correctly and safely embed that
plain text string in the appropriate context.

When a data value is not plain text, you can make sure it is not over-escaped
by marking it with its type.

Types HTML, JS, URL, and others from content.go can carry safe content that is
exempted from escaping.

The template

  Hello, {{.}}!

can be invoked with

  tmpl.Execute(out, HTML(`<b>World</b>`))

to produce

  Hello, World!

instead of the

  Hello, <b>World<b>!

that would have been produced if {{.}} was a regular string.

Security Model

http://js-quasis-libraries-and-repl.googlecode.com/svn/trunk/safetemplate.html#problem_definition defines "safe" as used by this package.

This package assumes that template authors are trusted, that Execute's data
parameter is not, and seeks to preserve the properties below in the face
of untrusted data:

Structure Preservation Property
"... when a template author writes an HTML tag in a safe templating language,
the browser will interpret the corresponding portion of the output as a tag
regardless of the values of untrusted data, and similarly for other structures
such as attribute boundaries and JS and CSS string boundaries."

Code Effect Property
"... only code specified by the template author should run as a result of
injecting the template output into a page and all code specified by the
template author should run as a result of the same."

Least Surprise Property
"A developer (or code reviewer) familiar with HTML, CSS, and JavaScript, who
knows that contextual autoescaping happens should be able to look at a {{.}}
and correctly infer what sanitization happens."
*/
package template
<commit_msg>html/template: fix documentation formatting<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
Package template (html/template) is a specialization of package text/template
that automates the construction of HTML output that is safe against code
injection.

Introduction

This package wraps package template so you can use the standard template API
to parse and execute templates.

  set, err := new(template.Set).Parse(...)
  // Error checking elided
  err = set.Execute(out, "Foo", data)

If successful, set will now be injection-safe. Otherwise, err is an error
defined in the docs for ErrorCode.

HTML templates treat data values as plain text which should be encoded so they
can be safely embedded in an HTML document. The escaping is contextual, so
actions can appear within JavaScript, CSS, and URI contexts.

The security model used by this package assumes that template authors are
trusted, while Execute's data parameter is not. More details are provided below.

Example

  import "text/template"
  ...
  t, err := (&template.Set{}).Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
  err = t.Execute(out, "T", "")

produces

  Hello, !

but with contextual autoescaping,

  import "html/template"
  ...
  t, err := (&template.Set{}).Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
  err = t.Execute(out, "T", "")

produces safe, escaped HTML output

  Hello, <script>alert('you have been pwned')</script>!

Contexts

This package understands HTML, CSS, JavaScript, and URIs. It adds sanitizing
functions to each simple action pipeline, so given the excerpt

  {{.}}

At parse time each {{.}} is overwritten to add escaping functions as necessary,
in this case,

  {{. | html}}

Errors

See the documentation of ErrorCode for details.

A fuller picture

The rest of this package comment may be skipped on first reading; it includes
details necessary to understand escaping contexts and error messages. Most users
will not need to understand these details.

Contexts

Assuming {{.}} is `O'Reilly: How are <i>you</i>?`, the table below shows
how {{.}} appears when used in the context to the left.

  Context                          {{.}} After
  {{.}}                            O'Reilly: How are <i>you</i>?
                  O'Reilly: How are you?
                  O'Reilly: How are %3ci%3eyou%3c/i%3e?
                O'Reilly%3a%20How%20are%3ci%3e...%3f
               O\x27Reilly: How are \x3ci\x3eyou...?
                 "O\x27Reilly: How are \x3ci\x3eyou...?"
       O\x27Reilly: How are \x3ci\x3eyou...\x3f

If used in an unsafe context, then the value might be filtered out:

  Context                          {{.}} After
                   #ZgotmplZ

since "O'Reilly:" is not an allowed protocol like "http:".

If {{.}} is the innocuous word, `left`, then it can appear more widely,

  Context                              {{.}} After
  {{.}}                                left
                      left
                       left
                      left
                  left
          left
               left
         left
    left
     left

Non-string values can be used in JavaScript contexts.
If {{.}} is

  []struct{A,B string}{ "foo", "bar" }

in the escaped template

then the template output is

See package json to understand how non-string content is marshalled for
embedding in JavaScript contexts.

Typed Strings

By default, this package assumes that all pipelines produce a plain text string.
It adds escaping pipeline stages necessary to correctly and safely embed that
plain text string in the appropriate context.

When a data value is not plain text, you can make sure it is not over-escaped
by marking it with its type.

Types HTML, JS, URL, and others from content.go can carry safe content that is
exempted from escaping.

The template

  Hello, {{.}}!

can be invoked with

  tmpl.Execute(out, HTML(`<b>World</b>`))

to produce

  Hello, World!

instead of the

  Hello, <b>World<b>!

that would have been produced if {{.}} was a regular string.

Security Model

http://js-quasis-libraries-and-repl.googlecode.com/svn/trunk/safetemplate.html#problem_definition defines "safe" as used by this package.

This package assumes that template authors are trusted, that Execute's data
parameter is not, and seeks to preserve the properties below in the face
of untrusted data:

Structure Preservation Property
"... when a template author writes an HTML tag in a safe templating language,
the browser will interpret the corresponding portion of the output as a tag
regardless of the values of untrusted data, and similarly for other structures
such as attribute boundaries and JS and CSS string boundaries."

Code Effect Property
"... only code specified by the template author should run as a result of
injecting the template output into a page and all code specified by the
template author should run as a result of the same."

Least Surprise Property
"A developer (or code reviewer) familiar with HTML, CSS, and JavaScript, who
knows that contextual autoescaping happens should be able to look at a {{.}}
and correctly infer what sanitization happens."
*/
package template
<|endoftext|>


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

package sync_test

import (
	"fmt"
	"net/http"
	"sync"
)

// This example fetches several URLs concurrently,
// using a WaitGroup to block until all the fetches are complete.
func ExampleWaitGroup() {
	var wg sync.WaitGroup
	var urls = []string{
		"http://www.golang.org/",
		"http://www.google.com/",
		"http://www.somestupidname.com/",
	}
	for _, url := range urls {
		// Increment the WaitGroup counter.
		wg.Add(1)
		// Launch a goroutine to fetch the URL.
		go func(url string) {
			// Fetch the URL.
			http.Get(url)
			// Decrement the counter.
			wg.Done()
		}(url)
	}
	// Wait for all HTTP fetches to complete.
	wg.Wait()
}

func ExampleOnce() {
	var once sync.Once
	onceBody := func() {
		fmt.Printf("Only once\n")
	}
	done := make(chan bool)
	for i := 0; i < 10; i++ {
		go func() {
			once.Do(onceBody)
			done <- true
		}()
	}
	for i := 0; i < 10; i++ {
		<-done
	}
	// Output:
	// Only once
}
<commit_msg>sync: improve WaitGroup example by putting the call to Done in a deferred block. This makes hangs in the waiting code less likely if a goroutine exits abnormally.<commit_after>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sync_test

import (
	"fmt"
	"net/http"
	"sync"
)

// This example fetches several URLs concurrently,
// using a WaitGroup to block until all the fetches are complete.
func ExampleWaitGroup() {
	var wg sync.WaitGroup
	var urls = []string{
		"http://www.golang.org/",
		"http://www.google.com/",
		"http://www.somestupidname.com/",
	}
	for _, url := range urls {
		// Increment the WaitGroup counter.
		wg.Add(1)
		// Launch a goroutine to fetch the URL.
		go func(url string) {
			// Decrement the counter when the goroutine completes.
			defer wg.Done()
			// Fetch the URL.
			http.Get(url)
		}(url)
	}
	// Wait for all HTTP fetches to complete.
	wg.Wait()
}

func ExampleOnce() {
	var once sync.Once
	onceBody := func() {
		fmt.Println("Only once")
	}
	done := make(chan bool)
	for i := 0; i < 10; i++ {
		go func() {
			once.Do(onceBody)
			done <- true
		}()
	}
	for i := 0; i < 10; i++ {
		<-done
	}
	// Output:
	// Only once
}
<|endoftext|>


<commit_before>package v7_test

import (
	"errors"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"

	"code.cloudfoundry.org/cli/actor/actionerror"
	"code.cloudfoundry.org/cli/actor/v7action"
	"code.cloudfoundry.org/cli/command/commandfakes"
	"code.cloudfoundry.org/cli/command/translatableerror"
	. "code.cloudfoundry.org/cli/command/v7"
	"code.cloudfoundry.org/cli/command/v7/v7fakes"
	"code.cloudfoundry.org/cli/util/configv3"
	"code.cloudfoundry.org/cli/util/ui"

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

var _ = Describe("download-droplet Command", func() {

	var (
		cmd             DownloadDropletCommand
		testUI          *ui.UI
		fakeConfig      *commandfakes.FakeConfig
		fakeSharedActor *commandfakes.FakeSharedActor
		fakeActor       *v7fakes.FakeActor
		binaryName      string
		executeErr      error
	)

	BeforeEach(func() {
		testUI = ui.NewTestUI(nil, NewBuffer(), NewBuffer())
		fakeConfig = new(commandfakes.FakeConfig)
		fakeSharedActor = new(commandfakes.FakeSharedActor)
		fakeActor = new(v7fakes.FakeActor)

		cmd = DownloadDropletCommand{
			BaseCommand: BaseCommand{
				UI:          testUI,
				Config:      fakeConfig,
				SharedActor: fakeSharedActor,
				Actor:       fakeActor,
			},
		}

		cmd.RequiredArgs.AppName = "some-app"

		binaryName = "faceman"
		fakeConfig.BinaryNameReturns(binaryName)
		fakeConfig.HasTargetedOrganizationReturns(true)
		fakeConfig.TargetedOrganizationReturns(configv3.Organization{Name: "some-org"})
		fakeConfig.HasTargetedSpaceReturns(true)
		fakeConfig.TargetedSpaceReturns(configv3.Space{
			GUID: "some-space-guid",
			Name: "some-space"})
		fakeConfig.CurrentUserReturns(
			configv3.User{Name: "some-user"},
			nil)
	})

	JustBeforeEach(func() {
		executeErr = cmd.Execute(nil)
	})

	When("checking target fails", func() {
		BeforeEach(func() {
			fakeSharedActor.CheckTargetReturns(actionerror.NotLoggedInError{BinaryName: binaryName})
		})

		It("returns an error if the check fails", func() {
			Expect(executeErr).To(MatchError(actionerror.NotLoggedInError{BinaryName: "faceman"}))

			Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1))
			checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0)
			Expect(checkTargetedOrg).To(BeTrue())
			Expect(checkTargetedSpace).To(BeTrue())
		})
	})

	When("downloading the droplet succeeds", func() {
		var pathToDropletFile string

		BeforeEach(func() {
			fakeActor.DownloadCurrentDropletByAppNameReturns([]byte("some-droplet"), "some-droplet-guid", v7action.Warnings{"some-warning"}, nil)

			currentDir, _ := os.Getwd()
			pathToDropletFile = filepath.Join(currentDir, "droplet_some-droplet-guid.tgz")
		})

		AfterEach(func() {
			Expect(os.Remove(pathToDropletFile)).ToNot(HaveOccurred())
		})

		It("creates a droplet tarball in the current directory", func() {
			Expect(executeErr).ToNot(HaveOccurred())

			Expect(fakeActor.DownloadCurrentDropletByAppNameCallCount()).To(Equal(1))
			appArg, spaceGUIDArg := fakeActor.DownloadCurrentDropletByAppNameArgsForCall(0)
			Expect(appArg).To(Equal("some-app"))
			Expect(spaceGUIDArg).To(Equal("some-space-guid"))

			fileContents, err := ioutil.ReadFile(pathToDropletFile)
			Expect(err).ToNot(HaveOccurred())
			Expect(string(fileContents)).To(Equal("some-droplet"))
		})

		It("displays the file it created and returns no errors", func() {
			Expect(testUI.Out).To(Say("Downloading current droplet for app some-app in org some-org / space some-space as some-user..."))
			Expect(testUI.Err).To(Say("some-warning"))
			Expect(testUI.Out).To(Say(`Droplet downloaded successfully at .*droplet_some-droplet-guid.tgz`))
			Expect(testUI.Out).To(Say("OK"))
			Expect(executeErr).ToNot(HaveOccurred())
		})
	})

	When("the droplet guid is passed in", func() {
		var pathToDropletFile string

		BeforeEach(func() {
			cmd.Droplet = "some-droplet-guid"
			fakeActor.DownloadDropletByGUIDAndAppNameReturns([]byte("some-droplet"), v7action.Warnings{"some-warning"}, nil)

			pathToDropletFile = filepath.Join("droplet_some-droplet-guid.tgz")
		})

		AfterEach(func() {
			Expect(os.Remove("droplet_some-droplet-guid.tgz")).ToNot(HaveOccurred())
		})

		It("creates a droplet tarball in the current directory", func() {
			Expect(executeErr).ToNot(HaveOccurred())

			Expect(fakeActor.DownloadDropletByGUIDAndAppNameCallCount()).To(Equal(1))
			dropletGUIDArg, appArg, spaceGUIDArg := fakeActor.DownloadDropletByGUIDAndAppNameArgsForCall(0)
			Expect(dropletGUIDArg).To(Equal("some-droplet-guid"))
			Expect(appArg).To(Equal("some-app"))
			Expect(spaceGUIDArg).To(Equal("some-space-guid"))

			fileContents, err := ioutil.ReadFile(pathToDropletFile)
			Expect(err).ToNot(HaveOccurred())
			Expect(string(fileContents)).To(Equal("some-droplet"))
		})

		It("displays the file it created and returns no errors", func() {
			Expect(testUI.Out).To(Say("Downloading droplet some-droplet-guid for app some-app in org some-org / space some-space as some-user..."))
			Expect(testUI.Err).To(Say("some-warning"))
			Expect(testUI.Out).To(Say(`Droplet downloaded successfully at .*droplet_some-droplet-guid.tgz`))
			Expect(testUI.Out).To(Say("OK"))
			Expect(executeErr).ToNot(HaveOccurred())
		})
	})

	When("a path to a file is passed in", func() {
		BeforeEach(func() {
			cmd.Path = "some-file.tgz"
			fakeActor.DownloadCurrentDropletByAppNameReturns([]byte("some-droplet"), "some-droplet-guid", v7action.Warnings{"some-warning"}, nil)
		})

		AfterEach(func() {
			Expect(os.Remove(cmd.Path)).ToNot(HaveOccurred())
		})

		It("creates a droplet tarball at the specified path", func() {
			Expect(executeErr).ToNot(HaveOccurred())

			fileContents, err := ioutil.ReadFile(cmd.Path)
			Expect(err).ToNot(HaveOccurred())
			Expect(string(fileContents)).To(Equal("some-droplet"))
		})

		It("displays the file it created and returns no errors", func() {
			Expect(testUI.Out).To(Say("Downloading current droplet for app some-app in org some-org / space some-space as some-user..."))
			Expect(testUI.Err).To(Say("some-warning"))
			Expect(testUI.Out).To(Say(`Droplet downloaded successfully at %s`, cmd.Path))
			Expect(testUI.Out).To(Say("OK"))
			Expect(executeErr).ToNot(HaveOccurred())
		})
	})

	When("a path to an existing directory is passed in", func() {
		BeforeEach(func() {
			tmpDir, err := ioutil.TempDir("", "droplets")
			Expect(err).NotTo(HaveOccurred())
			cmd.Path = tmpDir

			fakeActor.DownloadCurrentDropletByAppNameReturns([]byte("some-droplet"), "some-droplet-guid", v7action.Warnings{"some-warning"}, nil)
		})

		AfterEach(func() {
			Expect(os.RemoveAll(cmd.Path)).ToNot(HaveOccurred())
		})

		It("creates a droplet tarball at the specified path", func() {
			Expect(executeErr).ToNot(HaveOccurred())

			fileContents, err := ioutil.ReadFile(filepath.Join(cmd.Path, "droplet_some-droplet-guid.tgz"))
			Expect(err).ToNot(HaveOccurred())
			Expect(string(fileContents)).To(Equal("some-droplet"))
		})

		It("displays the file it created and returns no errors", func() {
			Expect(executeErr).ToNot(HaveOccurred())
			Expect(testUI.Out).To(Say("Downloading current droplet for app some-app in org some-org / space some-space as some-user..."))
			Expect(testUI.Err).To(Say("some-warning"))
			pathRegExp := regexp.QuoteMeta(filepath.Join(cmd.Path, "droplet_some-droplet-guid.tgz"))
			Expect(testUI.Out).To(Say(`Droplet downloaded successfully at %s`, pathRegExp))
			Expect(testUI.Out).To(Say("OK"))
		})
	})

	When("a path to a file in an invalid directory is passed in", func() {
		BeforeEach(func() {
			cmd.Path = "not/exist/some-file.tgz"
			fakeActor.DownloadCurrentDropletByAppNameReturns([]byte("some-droplet"), "some-droplet-guid", v7action.Warnings{"some-warning"}, nil)
		})

		It("returns an appropriate error", func() {
			_, ok := executeErr.(translatableerror.DropletFileError)
			Expect(ok).To(BeTrue())
		})
	})

	When("there is an error downloading the droplet", func() {
		BeforeEach(func() {
			fakeActor.DownloadCurrentDropletByAppNameReturns([]byte{}, "", v7action.Warnings{"some-warning"}, errors.New("something went wrong"))
		})

		It("displays warnings and returns an error", func() {
			Expect(testUI.Err).To(Say("some-warning"))
			Expect(executeErr).To(MatchError("something went wrong"))
		})
	})

	When("the app does not have a current droplet", func() {
		BeforeEach(func() {
			fakeActor.DownloadCurrentDropletByAppNameReturns([]byte{}, "", v7action.Warnings{"some-warning"}, actionerror.DropletNotFoundError{})
		})

		It("displays warnings and returns an error", func() {
			Expect(testUI.Err).To(Say("some-warning"))
			Expect(executeErr).To(MatchError(translatableerror.NoDropletForAppError{AppName: "some-app"}))
		})
	})
})
<commit_msg>test(droplets): remove file name collisions<commit_after>package v7_test

import (
	"errors"
	"fmt"
	"io/ioutil"
	"math/rand"
	"os"
	"path/filepath"
	"regexp"

	"code.cloudfoundry.org/cli/actor/actionerror"
	"code.cloudfoundry.org/cli/actor/v7action"
	"code.cloudfoundry.org/cli/command/commandfakes"
	"code.cloudfoundry.org/cli/command/translatableerror"
	. "code.cloudfoundry.org/cli/command/v7"
	"code.cloudfoundry.org/cli/command/v7/v7fakes"
	"code.cloudfoundry.org/cli/util/configv3"
	"code.cloudfoundry.org/cli/util/ui"

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

var _ = Describe("download-droplet Command", func() {

	var (
		cmd             DownloadDropletCommand
		testUI          *ui.UI
		fakeConfig      *commandfakes.FakeConfig
		fakeSharedActor *commandfakes.FakeSharedActor
		fakeActor       *v7fakes.FakeActor
		binaryName      string
		executeErr      error
	)

	BeforeEach(func() {
		testUI = ui.NewTestUI(nil, NewBuffer(), NewBuffer())
		fakeConfig = new(commandfakes.FakeConfig)
		fakeSharedActor = new(commandfakes.FakeSharedActor)
		fakeActor = new(v7fakes.FakeActor)

		cmd = DownloadDropletCommand{
			BaseCommand: BaseCommand{
				UI:          testUI,
				Config:      fakeConfig,
				SharedActor: fakeSharedActor,
				Actor:       fakeActor,
			},
		}

		cmd.RequiredArgs.AppName = "some-app"

		binaryName = "faceman"
		fakeConfig.BinaryNameReturns(binaryName)
		fakeConfig.HasTargetedOrganizationReturns(true)
		fakeConfig.TargetedOrganizationReturns(configv3.Organization{Name: "some-org"})
		fakeConfig.HasTargetedSpaceReturns(true)
		fakeConfig.TargetedSpaceReturns(configv3.Space{
			GUID: "some-space-guid",
			Name: "some-space"})
		fakeConfig.CurrentUserReturns(
			configv3.User{Name: "some-user"},
			nil)
	})

	JustBeforeEach(func() {
		executeErr = cmd.Execute(nil)
	})

	When("checking target fails", func() {
		BeforeEach(func() {
			fakeSharedActor.CheckTargetReturns(actionerror.NotLoggedInError{BinaryName: binaryName})
		})

		It("returns an error if the check fails", func() {
			Expect(executeErr).To(MatchError(actionerror.NotLoggedInError{BinaryName: "faceman"}))

			Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1))
			checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0)
			Expect(checkTargetedOrg).To(BeTrue())
			Expect(checkTargetedSpace).To(BeTrue())
		})
	})

	When("downloading the droplet succeeds", func() {
		var (
			pathToDropletFile string
			dropletGUID       string
		)

		BeforeEach(func() {
			dropletGUID = fmt.Sprintf("fake-droplet-guid-%d", rand.Uint64())
			fakeActor.DownloadCurrentDropletByAppNameReturns([]byte("some-droplet-bytes"), dropletGUID, v7action.Warnings{"some-warning"}, nil)

			currentDir, _ := os.Getwd()
			pathToDropletFile = filepath.Join(currentDir, fmt.Sprintf("droplet_%s.tgz", dropletGUID))
		})

		AfterEach(func() {
			Expect(os.Remove(pathToDropletFile)).ToNot(HaveOccurred())
		})

		It("creates a droplet tarball in the current directory", func() {
			Expect(executeErr).ToNot(HaveOccurred())

			Expect(fakeActor.DownloadCurrentDropletByAppNameCallCount()).To(Equal(1))
			appArg, spaceGUIDArg := fakeActor.DownloadCurrentDropletByAppNameArgsForCall(0)
			Expect(appArg).To(Equal("some-app"))
			Expect(spaceGUIDArg).To(Equal("some-space-guid"))

			fileContents, err := ioutil.ReadFile(pathToDropletFile)
			Expect(err).ToNot(HaveOccurred())
			Expect(string(fileContents)).To(Equal("some-droplet-bytes"))
		})

		It("displays the file it created and returns no errors", func() {
			Expect(testUI.Out).To(Say("Downloading current droplet for app some-app in org some-org / space some-space as some-user..."))
			Expect(testUI.Err).To(Say("some-warning"))
			Expect(testUI.Out).To(Say(`Droplet downloaded successfully at .*droplet_%s.tgz`, dropletGUID))
			Expect(testUI.Out).To(Say("OK"))
			Expect(executeErr).ToNot(HaveOccurred())
		})
	})

	When("the droplet guid is passed in", func() {
		var (
			dropletGUID       string
			pathToDropletFile string
		)

		BeforeEach(func() {
			dropletGUID = fmt.Sprintf("fake-droplet-guid-%d", rand.Uint64())
			pathToDropletFile = fmt.Sprintf("droplet_%s.tgz", dropletGUID)

			setFlag(&cmd, "--droplet", dropletGUID)

			fakeActor.DownloadDropletByGUIDAndAppNameReturns([]byte("some-droplet-bytes"), v7action.Warnings{"some-warning"}, nil)
		})

		AfterEach(func() {
			Expect(os.Remove(pathToDropletFile)).ToNot(HaveOccurred())
		})

		It("creates a droplet tarball in the current directory", func() {
			Expect(executeErr).ToNot(HaveOccurred())

			Expect(fakeActor.DownloadDropletByGUIDAndAppNameCallCount()).To(Equal(1))
			dropletGUIDArg, appArg, spaceGUIDArg := fakeActor.DownloadDropletByGUIDAndAppNameArgsForCall(0)
			Expect(dropletGUIDArg).To(Equal(dropletGUID))
			Expect(appArg).To(Equal("some-app"))
			Expect(spaceGUIDArg).To(Equal("some-space-guid"))

			fileContents, err := ioutil.ReadFile(pathToDropletFile)
			Expect(err).ToNot(HaveOccurred())
			Expect(string(fileContents)).To(Equal("some-droplet-bytes"))
		})

		It("displays the file it created and returns no errors", func() {
			Expect(testUI.Out).To(Say("Downloading droplet %s for app some-app in org some-org / space some-space as some-user...", dropletGUID))
			Expect(testUI.Err).To(Say("some-warning"))
			Expect(testUI.Out).To(Say(`Droplet downloaded successfully at .*droplet_%s.tgz`, dropletGUID))
			Expect(testUI.Out).To(Say("OK"))
			Expect(executeErr).ToNot(HaveOccurred())
		})
	})

	When("a path to a file is passed in", func() {
		var filePath string
		BeforeEach(func() {
			filePath = fmt.Sprintf("fake-file-%d", rand.Uint64())

			setFlag(&cmd, "--path", filePath)
			fakeActor.DownloadCurrentDropletByAppNameReturns([]byte("some-droplet"), "some-droplet-guid", v7action.Warnings{"some-warning"}, nil)
		})

		AfterEach(func() {
			Expect(os.Remove(filePath)).ToNot(HaveOccurred())
		})

		It("creates a droplet tarball at the specified path", func() {
			Expect(executeErr).ToNot(HaveOccurred())

			fileContents, err := ioutil.ReadFile(filePath)
			Expect(err).ToNot(HaveOccurred())
			Expect(string(fileContents)).To(Equal("some-droplet"))
		})

		It("displays the file it created and returns no errors", func() {
			Expect(testUI.Out).To(Say("Downloading current droplet for app some-app in org some-org / space some-space as some-user..."))
			Expect(testUI.Err).To(Say("some-warning"))
			Expect(testUI.Out).To(Say(`Droplet downloaded successfully at %s`, filePath))
			Expect(testUI.Out).To(Say("OK"))
			Expect(executeErr).ToNot(HaveOccurred())
		})
	})

	When("a path to an existing directory is passed in", func() {
		var tmpDir string

		BeforeEach(func() {
			var err error
			tmpDir, err = ioutil.TempDir("", "droplets")
			Expect(err).NotTo(HaveOccurred())

			setFlag(&cmd, "--path", tmpDir)

			fakeActor.DownloadCurrentDropletByAppNameReturns([]byte("some-droplet"), "some-droplet-guid", v7action.Warnings{"some-warning"}, nil)
		})

		AfterEach(func() {
			Expect(os.RemoveAll(tmpDir)).ToNot(HaveOccurred())
		})

		It("creates a droplet tarball at the specified path", func() {
			Expect(executeErr).ToNot(HaveOccurred())

			fileContents, err := ioutil.ReadFile(filepath.Join(tmpDir, "droplet_some-droplet-guid.tgz"))
			Expect(err).ToNot(HaveOccurred())
			Expect(string(fileContents)).To(Equal("some-droplet"))
		})

		It("displays the file it created and returns no errors", func() {
			Expect(executeErr).ToNot(HaveOccurred())
			Expect(testUI.Out).To(Say("Downloading current droplet for app some-app in org some-org / space some-space as some-user..."))
			Expect(testUI.Err).To(Say("some-warning"))
			pathRegExp := regexp.QuoteMeta(filepath.Join(tmpDir, "droplet_some-droplet-guid.tgz"))
			Expect(testUI.Out).To(Say(`Droplet downloaded successfully at %s`, pathRegExp))
			Expect(testUI.Out).To(Say("OK"))
		})
	})

	When("a path to a file in an invalid directory is passed in", func() {
		BeforeEach(func() {
			cmd.Path = "not/exist/some-file.tgz"
			fakeActor.DownloadCurrentDropletByAppNameReturns([]byte("some-droplet"), "some-droplet-guid", v7action.Warnings{"some-warning"}, nil)
		})

		It("returns an appropriate error", func() {
			_, ok := executeErr.(translatableerror.DropletFileError)
			Expect(ok).To(BeTrue())
		})
	})

	When("there is an error downloading the droplet", func() {
		BeforeEach(func() {
			fakeActor.DownloadCurrentDropletByAppNameReturns([]byte{}, "", v7action.Warnings{"some-warning"}, errors.New("something went wrong"))
		})

		It("displays warnings and returns an error", func() {
			Expect(testUI.Err).To(Say("some-warning"))
			Expect(executeErr).To(MatchError("something went wrong"))
		})
	})

	When("the app does not have a current droplet", func() {
		BeforeEach(func() {
			fakeActor.DownloadCurrentDropletByAppNameReturns([]byte{}, "", v7action.Warnings{"some-warning"}, actionerror.DropletNotFoundError{})
		})

		It("displays warnings and returns an error", func() {
			Expect(testUI.Err).To(Say("some-warning"))
			Expect(executeErr).To(MatchError(translatableerror.NoDropletForAppError{AppName: "some-app"}))
		})
	})
})
<|endoftext|>


<commit_before>// Copyright © 2017 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package router

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

	pb_broker "github.com/TheThingsNetwork/api/broker"
	"github.com/TheThingsNetwork/api/logfields"
	pb_protocol "github.com/TheThingsNetwork/api/protocol"
	pb_lorawan "github.com/TheThingsNetwork/api/protocol/lorawan"
	pb "github.com/TheThingsNetwork/api/router"
	"github.com/TheThingsNetwork/api/trace"
	"github.com/TheThingsNetwork/ttn/core/band"
	"github.com/TheThingsNetwork/ttn/core/router/gateway"
	"github.com/TheThingsNetwork/ttn/utils/errors"
)

func (r *router) HandleActivation(gatewayID string, activation *pb.DeviceActivationRequest) (res *pb.DeviceActivationResponse, err error) {
	ctx := r.Ctx.WithField("GatewayID", gatewayID).WithFields(logfields.ForMessage(activation))
	start := time.Now()
	var gateway *gateway.Gateway
	var forwarded bool

	r.RegisterReceived(activation)
	defer func() {
		if err != nil {
			activation.Trace = activation.Trace.WithEvent(trace.DropEvent, "reason", err)
			if forwarded {
				ctx.WithError(err).Debug("Did not handle activation")
			} else if gateway != nil && gateway.MonitorStream != nil {
				ctx.WithError(err).Warn("Could not handle activation")
				gateway.MonitorStream.Send(activation)
			}
		} else {
			r.RegisterHandled(activation)
			ctx.WithField("Duration", time.Now().Sub(start)).Info("Handled activation")
		}
	}()
	r.status.activations.Mark(1)

	activation.Trace = activation.Trace.WithEvent(trace.ReceiveEvent, "gateway", gatewayID)

	gateway = r.getGateway(gatewayID)
	gateway.LastSeen = time.Now()

	uplink := &pb.UplinkMessage{
		Payload:          activation.Payload,
		ProtocolMetadata: activation.ProtocolMetadata,
		GatewayMetadata:  activation.GatewayMetadata,
		Trace:            activation.Trace,
	}

	if err = gateway.HandleUplink(uplink); err != nil {
		return nil, err
	}

	if !gateway.Schedule.IsActive() {
		return nil, errors.NewErrInternal(fmt.Sprintf("Gateway %s not available for downlink", gatewayID))
	}

	downlinkOptions := r.buildDownlinkOptions(uplink, true, gateway)
	activation.Trace = uplink.Trace.WithEvent(trace.BuildDownlinkEvent,
		"options", len(downlinkOptions),
	)

	// Find Broker
	brokers, err := r.Discovery.GetAll("broker")
	if err != nil {
		return nil, err
	}

	// Prepare request
	request := &pb_broker.DeviceActivationRequest{
		Payload:          activation.Payload,
		DevEUI:           activation.DevEUI,
		AppEUI:           activation.AppEUI,
		ProtocolMetadata: activation.ProtocolMetadata,
		GatewayMetadata:  activation.GatewayMetadata,
		ActivationMetadata: &pb_protocol.ActivationMetadata{
			Protocol: &pb_protocol.ActivationMetadata_LoRaWAN{
				LoRaWAN: &pb_lorawan.ActivationMetadata{
					AppEUI: activation.AppEUI,
					DevEUI: activation.DevEUI,
				},
			},
		},
		DownlinkOptions: downlinkOptions,
		Trace:           activation.Trace,
	}

	// Prepare LoRaWAN activation
	status, err := gateway.Status.Get()
	if err != nil {
		return nil, err
	}
	region := status.FrequencyPlan
	if region == "" {
		region = band.Guess(uplink.GatewayMetadata.Frequency)
	}
	band, err := band.Get(region)
	if err != nil {
		return nil, err
	}
	lorawan := request.ActivationMetadata.GetLoRaWAN()
	lorawan.FrequencyPlan = pb_lorawan.FrequencyPlan(pb_lorawan.FrequencyPlan_value[region])
	lorawan.Rx1DROffset = 0
	lorawan.Rx2DR = uint32(band.RX2DataRate)
	lorawan.RxDelay = uint32(band.ReceiveDelay1.Seconds())
	if band.CFList != nil {
		lorawan.CFList = new(pb_lorawan.CFList)
		for _, freq := range band.CFList {
			lorawan.CFList.Freq = append(lorawan.CFList.Freq, freq)
		}
	}

	ctx = ctx.WithField("NumBrokers", len(brokers))
	request.Trace = request.Trace.WithEvent(trace.ForwardEvent,
		"brokers", len(brokers),
	)

	if gateway != nil && gateway.MonitorStream != nil {
		forwarded = true
		gateway.MonitorStream.Send(activation)
	}

	// Forward to all brokers and collect responses
	var wg sync.WaitGroup
	responses := make(chan *pb_broker.DeviceActivationResponse, len(brokers))
	for _, broker := range brokers {
		broker, err := r.getBroker(broker)
		if err != nil {
			continue
		}

		// Do async request
		wg.Add(1)
		go func() {
			ctx, cancel := context.WithTimeout(r.Component.GetContext(""), 5*time.Second)
			defer cancel()
			res, err := broker.client.Activate(ctx, request)
			if err == nil && res != nil {
				responses <- res
			}
			wg.Done()
		}()
	}

	// Make sure to close channel when all requests are done
	go func() {
		wg.Wait()
		close(responses)
	}()

	var gotFirst bool
	for res := range responses {
		if gotFirst {
			ctx.Warn("Duplicate Activation Response")
		} else {
			gotFirst = true
			downlink := &pb_broker.DownlinkMessage{
				Payload:        res.Payload,
				Message:        res.Message,
				DownlinkOption: res.DownlinkOption,
				Trace:          res.Trace,
			}
			err := r.HandleDownlink(downlink)
			if err != nil {
				ctx.Warn("Could not send downlink for Activation")
				gotFirst = false // try again
			}
		}
	}

	// Activation not accepted by any broker
	if !gotFirst {
		ctx.Debug("Activation not accepted at this gateway")
		return nil, errors.New("Activation not accepted at this Gateway")
	}

	// Activation accepted by (at least one) broker
	ctx.Debug("Activation accepted")
	return &pb.DeviceActivationResponse{}, nil
}
<commit_msg>Sign activations only once<commit_after>// Copyright © 2017 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package router

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

	pb_broker "github.com/TheThingsNetwork/api/broker"
	"github.com/TheThingsNetwork/api/logfields"
	pb_protocol "github.com/TheThingsNetwork/api/protocol"
	pb_lorawan "github.com/TheThingsNetwork/api/protocol/lorawan"
	pb "github.com/TheThingsNetwork/api/router"
	"github.com/TheThingsNetwork/api/trace"
	"github.com/TheThingsNetwork/ttn/core/band"
	"github.com/TheThingsNetwork/ttn/core/router/gateway"
	"github.com/TheThingsNetwork/ttn/utils/errors"
)

func (r *router) HandleActivation(gatewayID string, activation *pb.DeviceActivationRequest) (res *pb.DeviceActivationResponse, err error) {
	ctx := r.Ctx.WithField("GatewayID", gatewayID).WithFields(logfields.ForMessage(activation))
	start := time.Now()
	var gateway *gateway.Gateway
	var forwarded bool

	r.RegisterReceived(activation)
	defer func() {
		if err != nil {
			activation.Trace = activation.Trace.WithEvent(trace.DropEvent, "reason", err)
			if forwarded {
				ctx.WithError(err).Debug("Did not handle activation")
			} else if gateway != nil && gateway.MonitorStream != nil {
				ctx.WithError(err).Warn("Could not handle activation")
				gateway.MonitorStream.Send(activation)
			}
		} else {
			r.RegisterHandled(activation)
			ctx.WithField("Duration", time.Now().Sub(start)).Info("Handled activation")
		}
	}()
	r.status.activations.Mark(1)

	activation.Trace = activation.Trace.WithEvent(trace.ReceiveEvent, "gateway", gatewayID)

	gateway = r.getGateway(gatewayID)
	gateway.LastSeen = time.Now()

	uplink := &pb.UplinkMessage{
		Payload:          activation.Payload,
		ProtocolMetadata: activation.ProtocolMetadata,
		GatewayMetadata:  activation.GatewayMetadata,
		Trace:            activation.Trace,
	}

	if err = gateway.HandleUplink(uplink); err != nil {
		return nil, err
	}

	if !gateway.Schedule.IsActive() {
		return nil, errors.NewErrInternal(fmt.Sprintf("Gateway %s not available for downlink", gatewayID))
	}

	downlinkOptions := r.buildDownlinkOptions(uplink, true, gateway)
	activation.Trace = uplink.Trace.WithEvent(trace.BuildDownlinkEvent,
		"options", len(downlinkOptions),
	)

	// Find Broker
	brokers, err := r.Discovery.GetAll("broker")
	if err != nil {
		return nil, err
	}

	// Prepare request
	request := &pb_broker.DeviceActivationRequest{
		Payload:          activation.Payload,
		DevEUI:           activation.DevEUI,
		AppEUI:           activation.AppEUI,
		ProtocolMetadata: activation.ProtocolMetadata,
		GatewayMetadata:  activation.GatewayMetadata,
		ActivationMetadata: &pb_protocol.ActivationMetadata{
			Protocol: &pb_protocol.ActivationMetadata_LoRaWAN{
				LoRaWAN: &pb_lorawan.ActivationMetadata{
					AppEUI: activation.AppEUI,
					DevEUI: activation.DevEUI,
				},
			},
		},
		DownlinkOptions: downlinkOptions,
		Trace:           activation.Trace,
	}

	// Prepare LoRaWAN activation
	status, err := gateway.Status.Get()
	if err != nil {
		return nil, err
	}
	region := status.FrequencyPlan
	if region == "" {
		region = band.Guess(uplink.GatewayMetadata.Frequency)
	}
	band, err := band.Get(region)
	if err != nil {
		return nil, err
	}
	lorawan := request.ActivationMetadata.GetLoRaWAN()
	lorawan.FrequencyPlan = pb_lorawan.FrequencyPlan(pb_lorawan.FrequencyPlan_value[region])
	lorawan.Rx1DROffset = 0
	lorawan.Rx2DR = uint32(band.RX2DataRate)
	lorawan.RxDelay = uint32(band.ReceiveDelay1.Seconds())
	if band.CFList != nil {
		lorawan.CFList = new(pb_lorawan.CFList)
		for _, freq := range band.CFList {
			lorawan.CFList.Freq = append(lorawan.CFList.Freq, freq)
		}
	}

	ctx = ctx.WithField("NumBrokers", len(brokers))
	request.Trace = request.Trace.WithEvent(trace.ForwardEvent,
		"brokers", len(brokers),
	)

	if gateway != nil && gateway.MonitorStream != nil {
		forwarded = true
		gateway.MonitorStream.Send(activation)
	}

	// Forward to all brokers and collect responses
	var wg sync.WaitGroup
	responses := make(chan *pb_broker.DeviceActivationResponse, len(brokers))
	rCtx, cancel := context.WithTimeout(r.Component.GetContext(""), 5*time.Second)
	defer cancel()
	for _, broker := range brokers {
		broker, err := r.getBroker(broker)
		if err != nil {
			continue
		}

		// Do async request
		wg.Add(1)
		go func() {
			res, err := broker.client.Activate(rCtx, request)
			if err == nil && res != nil {
				responses <- res
			}
			wg.Done()
		}()
	}

	// Make sure to close channel when all requests are done
	go func() {
		wg.Wait()
		close(responses)
	}()

	var gotFirst bool
	for res := range responses {
		if gotFirst {
			ctx.Warn("Duplicate Activation Response")
		} else {
			gotFirst = true
			downlink := &pb_broker.DownlinkMessage{
				Payload:        res.Payload,
				Message:        res.Message,
				DownlinkOption: res.DownlinkOption,
				Trace:          res.Trace,
			}
			err := r.HandleDownlink(downlink)
			if err != nil {
				ctx.Warn("Could not send downlink for Activation")
				gotFirst = false // try again
			}
		}
	}

	// Activation not accepted by any broker
	if !gotFirst {
		ctx.Debug("Activation not accepted at this gateway")
		return nil, errors.New("Activation not accepted at this Gateway")
	}

	// Activation accepted by (at least one) broker
	ctx.Debug("Activation accepted")
	return &pb.DeviceActivationResponse{}, nil
}
<|endoftext|>


<commit_before>package porterstemmer

import (
	"testing"
)

func TestHasSuffix(t *testing.T) {

	tests := make([]struct {
		S        []rune
		Suffix   []rune
		Expected bool
	}, 82)

	i := 0

	tests[i].S = []rune("ran")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("runner")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("runnar")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("runned")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("runnre")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = false
	i++

	// FIXME marty changed Expected
	// to false here because it seems
	// the contract does not support
	// suffix of same length as input
	// as this test implied
	tests[i].S = []rune("er")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("re")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("ran")
	tests[i].Suffix = []rune("ER")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("runner")
	tests[i].Suffix = []rune("ER")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("runnar")
	tests[i].Suffix = []rune("ER")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("runned")
	tests[i].Suffix = []rune("ER")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("runnre")
	tests[i].Suffix = []rune("ER")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("er")
	tests[i].Suffix = []rune("ER")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("re")
	tests[i].Suffix = []rune("ER")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("e")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("caresses")
	tests[i].Suffix = []rune("sses")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("ponies")
	tests[i].Suffix = []rune("ies")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("caress")
	tests[i].Suffix = []rune("ss")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("cats")
	tests[i].Suffix = []rune("s")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("feed")
	tests[i].Suffix = []rune("eed")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("agreed")
	tests[i].Suffix = []rune("eed")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("plastered")
	tests[i].Suffix = []rune("ed")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("bled")
	tests[i].Suffix = []rune("ed")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("motoring")
	tests[i].Suffix = []rune("ing")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("sing")
	tests[i].Suffix = []rune("ing")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("conflat")
	tests[i].Suffix = []rune("at")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("troubl")
	tests[i].Suffix = []rune("bl")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("siz")
	tests[i].Suffix = []rune("iz")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("happy")
	tests[i].Suffix = []rune("y")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("sky")
	tests[i].Suffix = []rune("y")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("relational")
	tests[i].Suffix = []rune("ational")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("conditional")
	tests[i].Suffix = []rune("tional")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("rational")
	tests[i].Suffix = []rune("tional")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("valenci")
	tests[i].Suffix = []rune("enci")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("hesitanci")
	tests[i].Suffix = []rune("anci")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("digitizer")
	tests[i].Suffix = []rune("izer")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("conformabli")
	tests[i].Suffix = []rune("abli")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("radicalli")
	tests[i].Suffix = []rune("alli")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("differentli")
	tests[i].Suffix = []rune("entli")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("vileli")
	tests[i].Suffix = []rune("eli")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("analogousli")
	tests[i].Suffix = []rune("ousli")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("vietnamization")
	tests[i].Suffix = []rune("ization")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("predication")
	tests[i].Suffix = []rune("ation")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("operator")
	tests[i].Suffix = []rune("ator")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("feudalism")
	tests[i].Suffix = []rune("alism")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("decisiveness")
	tests[i].Suffix = []rune("iveness")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("hopefulness")
	tests[i].Suffix = []rune("fulness")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("callousness")
	tests[i].Suffix = []rune("ousness")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("formaliti")
	tests[i].Suffix = []rune("aliti")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("sensitiviti")
	tests[i].Suffix = []rune("iviti")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("sensibiliti")
	tests[i].Suffix = []rune("biliti")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("triplicate")
	tests[i].Suffix = []rune("icate")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("formative")
	tests[i].Suffix = []rune("ative")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("formalize")
	tests[i].Suffix = []rune("alize")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("electriciti")
	tests[i].Suffix = []rune("iciti")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("electrical")
	tests[i].Suffix = []rune("ical")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("hopeful")
	tests[i].Suffix = []rune("ful")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("goodness")
	tests[i].Suffix = []rune("ness")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("revival")
	tests[i].Suffix = []rune("al")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("allowance")
	tests[i].Suffix = []rune("ance")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("inference")
	tests[i].Suffix = []rune("ence")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("airliner")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("gyroscopic")
	tests[i].Suffix = []rune("ic")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("adjustable")
	tests[i].Suffix = []rune("able")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("defensible")
	tests[i].Suffix = []rune("ible")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("irritant")
	tests[i].Suffix = []rune("ant")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("replacement")
	tests[i].Suffix = []rune("ement")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("adjustment")
	tests[i].Suffix = []rune("ment")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("dependent")
	tests[i].Suffix = []rune("ent")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("adoption")
	tests[i].Suffix = []rune("ion")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("homologou")
	tests[i].Suffix = []rune("ou")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("communism")
	tests[i].Suffix = []rune("ism")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("activate")
	tests[i].Suffix = []rune("ate")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("angulariti")
	tests[i].Suffix = []rune("iti")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("homologous")
	tests[i].Suffix = []rune("ous")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("effective")
	tests[i].Suffix = []rune("ive")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("bowdlerize")
	tests[i].Suffix = []rune("ize")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("probate")
	tests[i].Suffix = []rune("e")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("rate")
	tests[i].Suffix = []rune("e")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("cease")
	tests[i].Suffix = []rune("e")
	tests[i].Expected = true
	i++

	for _, datum := range tests {
		if actual := hasSuffix(datum.S, datum.Suffix); actual != datum.Expected {
			t.Errorf("Did NOT get what was expected for calling hasSuffix() on [%s] with suffix [%s]. Expect [%d] but got [%d]", string(datum.S), string(datum.Suffix), datum.Expected, actual)
		}
	}
}
<commit_msg>fix formatting issue identified by go vet<commit_after>package porterstemmer

import (
	"testing"
)

func TestHasSuffix(t *testing.T) {

	tests := make([]struct {
		S        []rune
		Suffix   []rune
		Expected bool
	}, 82)

	i := 0

	tests[i].S = []rune("ran")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("runner")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("runnar")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("runned")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("runnre")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = false
	i++

	// FIXME marty changed Expected
	// to false here because it seems
	// the contract does not support
	// suffix of same length as input
	// as this test implied
	tests[i].S = []rune("er")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("re")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("ran")
	tests[i].Suffix = []rune("ER")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("runner")
	tests[i].Suffix = []rune("ER")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("runnar")
	tests[i].Suffix = []rune("ER")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("runned")
	tests[i].Suffix = []rune("ER")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("runnre")
	tests[i].Suffix = []rune("ER")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("er")
	tests[i].Suffix = []rune("ER")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("re")
	tests[i].Suffix = []rune("ER")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("e")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = false
	i++

	tests[i].S = []rune("caresses")
	tests[i].Suffix = []rune("sses")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("ponies")
	tests[i].Suffix = []rune("ies")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("caress")
	tests[i].Suffix = []rune("ss")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("cats")
	tests[i].Suffix = []rune("s")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("feed")
	tests[i].Suffix = []rune("eed")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("agreed")
	tests[i].Suffix = []rune("eed")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("plastered")
	tests[i].Suffix = []rune("ed")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("bled")
	tests[i].Suffix = []rune("ed")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("motoring")
	tests[i].Suffix = []rune("ing")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("sing")
	tests[i].Suffix = []rune("ing")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("conflat")
	tests[i].Suffix = []rune("at")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("troubl")
	tests[i].Suffix = []rune("bl")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("siz")
	tests[i].Suffix = []rune("iz")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("happy")
	tests[i].Suffix = []rune("y")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("sky")
	tests[i].Suffix = []rune("y")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("relational")
	tests[i].Suffix = []rune("ational")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("conditional")
	tests[i].Suffix = []rune("tional")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("rational")
	tests[i].Suffix = []rune("tional")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("valenci")
	tests[i].Suffix = []rune("enci")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("hesitanci")
	tests[i].Suffix = []rune("anci")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("digitizer")
	tests[i].Suffix = []rune("izer")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("conformabli")
	tests[i].Suffix = []rune("abli")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("radicalli")
	tests[i].Suffix = []rune("alli")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("differentli")
	tests[i].Suffix = []rune("entli")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("vileli")
	tests[i].Suffix = []rune("eli")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("analogousli")
	tests[i].Suffix = []rune("ousli")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("vietnamization")
	tests[i].Suffix = []rune("ization")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("predication")
	tests[i].Suffix = []rune("ation")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("operator")
	tests[i].Suffix = []rune("ator")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("feudalism")
	tests[i].Suffix = []rune("alism")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("decisiveness")
	tests[i].Suffix = []rune("iveness")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("hopefulness")
	tests[i].Suffix = []rune("fulness")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("callousness")
	tests[i].Suffix = []rune("ousness")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("formaliti")
	tests[i].Suffix = []rune("aliti")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("sensitiviti")
	tests[i].Suffix = []rune("iviti")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("sensibiliti")
	tests[i].Suffix = []rune("biliti")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("triplicate")
	tests[i].Suffix = []rune("icate")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("formative")
	tests[i].Suffix = []rune("ative")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("formalize")
	tests[i].Suffix = []rune("alize")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("electriciti")
	tests[i].Suffix = []rune("iciti")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("electrical")
	tests[i].Suffix = []rune("ical")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("hopeful")
	tests[i].Suffix = []rune("ful")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("goodness")
	tests[i].Suffix = []rune("ness")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("revival")
	tests[i].Suffix = []rune("al")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("allowance")
	tests[i].Suffix = []rune("ance")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("inference")
	tests[i].Suffix = []rune("ence")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("airliner")
	tests[i].Suffix = []rune("er")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("gyroscopic")
	tests[i].Suffix = []rune("ic")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("adjustable")
	tests[i].Suffix = []rune("able")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("defensible")
	tests[i].Suffix = []rune("ible")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("irritant")
	tests[i].Suffix = []rune("ant")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("replacement")
	tests[i].Suffix = []rune("ement")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("adjustment")
	tests[i].Suffix = []rune("ment")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("dependent")
	tests[i].Suffix = []rune("ent")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("adoption")
	tests[i].Suffix = []rune("ion")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("homologou")
	tests[i].Suffix = []rune("ou")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("communism")
	tests[i].Suffix = []rune("ism")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("activate")
	tests[i].Suffix = []rune("ate")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("angulariti")
	tests[i].Suffix = []rune("iti")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("homologous")
	tests[i].Suffix = []rune("ous")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("effective")
	tests[i].Suffix = []rune("ive")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("bowdlerize")
	tests[i].Suffix = []rune("ize")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("probate")
	tests[i].Suffix = []rune("e")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("rate")
	tests[i].Suffix = []rune("e")
	tests[i].Expected = true
	i++

	tests[i].S = []rune("cease")
	tests[i].Suffix = []rune("e")
	tests[i].Expected = true
	i++

	for _, datum := range tests {
		if actual := hasSuffix(datum.S, datum.Suffix); actual != datum.Expected {
			t.Errorf("Did NOT get what was expected for calling hasSuffix() on [%s] with suffix [%s]. Expect [%t] but got [%t]", string(datum.S), string(datum.Suffix), datum.Expected, actual)
		}
	}
}
<|endoftext|>


<commit_before>package hamt32

import (
	"fmt"
	"strings"

	"github.com/lleo/go-hamt/key"
)

// implements nodeI
// implements leafI
type collisionLeaf struct {
	kvs []keyVal
}

func newCollisionLeaf(kvs []keyVal) *collisionLeaf {
	for _, kv := range kvs {
		if kvs[0].key.Hash30() != kv.key.Hash30() {
			panic(fmt.Sprintf("kvs[0].key.Hash30() != kv.key.Hash30()"))
		}
	}
	var leaf = new(collisionLeaf)
	leaf.kvs = append(leaf.kvs, kvs...)
	return leaf
}

func (l collisionLeaf) Hash30() uint32 {
	return l.kvs[0].key.Hash30()
}

func (l collisionLeaf) String() string {
	var kvstrs = make([]string, len(l.kvs))
	for i := 0; i < len(l.kvs); i++ {
		kvstrs[i] = l.kvs[i].String()
	}
	var jkvstr = strings.Join(kvstrs, ",")

	return fmt.Sprintf("collisionLeaf{hash30:%s, kvs:[]kv{%s}}",
		hash30String(l.Hash30()), jkvstr)
}

func (l collisionLeaf) get(key key.Key) (interface{}, bool) {
	for _, kv := range l.kvs {
		if kv.key.Equals(key) {
			return kv.val, true
		}
	}
	return nil, false
}

func (l collisionLeaf) put(key key.Key, val interface{}) (leafI, bool) {
	for _, kv := range l.kvs {
		if kv.key.Equals(key) {
			kv.val = val
			return l, false //key,val was not added, merely replaced
		}
	}
	l.kvs = append(l.kvs, keyVal{key, val})
	return l, true // key,val was added
}

func (l collisionLeaf) del(key key.Key) (interface{}, leafI, bool) {
	for i, kv := range l.kvs {
		if kv.key.Equals(key) {
			l.kvs = append(l.kvs[:i], l.kvs[i+1:]...)
			if len(l.kvs) == 1 {
				var fl = newFlatLeaf(l.kvs[0].key, l.kvs[0].val)
				return kv.val, fl, true
			}
			return kv.val, l, true
		}
	}
	return nil, l, false
}

func (l collisionLeaf) keyVals() []keyVal {
	//var r []keyVal
	//r = append(r, l.kvs...)
	//return r
	return l.kvs
}
<commit_msg>added a temporary log in collisionLeaf.put() call<commit_after>package hamt32

import (
	"fmt"
	"log"
	"strings"

	"github.com/lleo/go-hamt/key"
)

// implements nodeI
// implements leafI
type collisionLeaf struct {
	kvs []keyVal
}

func newCollisionLeaf(kvs []keyVal) *collisionLeaf {
	var leaf = new(collisionLeaf)
	leaf.kvs = append(leaf.kvs, kvs...)

	return leaf
}

func (l collisionLeaf) Hash30() uint32 {
	return l.kvs[0].key.Hash30()
}

func (l collisionLeaf) String() string {
	var kvstrs = make([]string, len(l.kvs))
	for i := 0; i < len(l.kvs); i++ {
		kvstrs[i] = l.kvs[i].String()
	}
	var jkvstr = strings.Join(kvstrs, ",")

	return fmt.Sprintf("collisionLeaf{hash30:%s, kvs:[]kv{%s}}",
		hash30String(l.Hash30()), jkvstr)
}

func (l collisionLeaf) get(key key.Key) (interface{}, bool) {
	for _, kv := range l.kvs {
		if kv.key.Equals(key) {
			return kv.val, true
		}
	}
	return nil, false
}

func (l collisionLeaf) put(key key.Key, val interface{}) (leafI, bool) {
	for _, kv := range l.kvs {
		if kv.key.Equals(key) {
			kv.val = val
			return l, false //key,val was not added, merely replaced
		}
	}
	l.kvs = append(l.kvs, keyVal{key, val})

	log.Printf("%s : %d\n", hash30String(l.Hash30()), len(l.kvs))

	return l, true // key,val was added
}

func (l collisionLeaf) del(key key.Key) (interface{}, leafI, bool) {
	for i, kv := range l.kvs {
		if kv.key.Equals(key) {
			l.kvs = append(l.kvs[:i], l.kvs[i+1:]...)
			if len(l.kvs) == 1 {
				var fl = newFlatLeaf(l.kvs[0].key, l.kvs[0].val)
				return kv.val, fl, true
			}
			return kv.val, l, true
		}
	}
	return nil, l, false
}

func (l collisionLeaf) keyVals() []keyVal {
	//var r []keyVal
	//r = append(r, l.kvs...)
	//return r
	return l.kvs
}
<|endoftext|>


<commit_before>package channel

import "fmt"

func Run() {
	c := gen(2, 3)
	out := sq(c)
	fmt.Println(<-out)
	fmt.Println(<-out)
}

func gen(nums ...int) <-chan int {
	out := make(chan int)
	go func() {
		for _, n := range nums {
			out <- n
		}
		close(out)
	}()
	return out
}

func sq(in <-chan int) <-chan int {
	out := make(chan int)
	go func() {
		for n := range in {
			out <- n * n
		}
		close(out)
	}()
	return out
}
<commit_msg>range get result<commit_after>package channel

import "fmt"

func Run() {
	c := gen(2, 3)
	out := sq(c)
	fmt.Println(<-out)
	fmt.Println(<-out)

	for v := range sq(sq(gen(2, 3))) {
		fmt.Println(v)
	}
}

func gen(nums ...int) <-chan int {
	out := make(chan int)
	go func() {
		for _, n := range nums {
			out <- n
		}
		close(out)
	}()
	return out
}

func sq(in <-chan int) <-chan int {
	out := make(chan int)
	go func() {
		for n := range in {
			out <- n * n
		}
		close(out)
	}()
	return out
}
<|endoftext|>


<commit_before>package discgo_test

import (
	"github.com/nhooyr/discgo"
	"os"
	"testing"
)

var (
	cID   = "331307058660114433"
	mID   = "334104659767590912"
	emoji = "🍰"
)

func TestClient_GetChannelMessages(t *testing.T) {
	params := &discgo.MessagesGetParams{
		Limit: 5,
	}
	messages, err := c.Channel(cID).Messages().Get(params)
	if err != nil {
		t.Fatal(err)
	}
	t.Log(messages[0].Content)
}

func TestClient_CreateMessage(t *testing.T) {
	f, err := os.Open("/Users/poonam566/Desktop/screenshot.png")
	if err != nil {
		t.Fatal(err)
	}
	defer f.Close()

	c.Channel(cID).Message(mID).Reactions().Emoji(emoji).User(uID).Delete()

	params := &discgo.MessageCreateParams{
		Content: "boar",
		File: &discgo.File{
			Name:    "screenshot.png",
			Content: f,
		},
		Embed: &discgo.Embed{
			Description: "heads",
			Image: &discgo.EmbedImage{
				URL: "attachment://screenshot.png",
			},
		},
	}
	msg, err := c.Channel(cID).Messages().Create(params)
	if err != nil {
		t.Fatal(err)
	}
	t.Log(msg)
}

func TestClient_CreateReaction(t *testing.T) {
	err := c.Channel(cID).Message(mID).Reactions().Create(emoji)
	if err != nil {
		t.Fatal(err)
	}
}

func TestClient_DeleteReaction(t *testing.T) {
	err := c.Channel(cID).Message(mID).Reaction(emoji, "@me").Delete()
	if err != nil {
		t.Fatal(err)
	}
}

func TestClient_GetReactions(t *testing.T) {
	users, err := c.GetReactions(cID, mID, emoji)
	if err != nil {
		t.Fatal(err)
	}
	t.Log(users[0].Username)
}

func TestClient_DeleteReactions(t *testing.T) {
	err := c.DeleteReactions(cID, mID)
	if err != nil {
		t.Fatal(err)
	}
}

func TestClient_UpdateMessage(t *testing.T) {
	params := &discgo.MessageEditParams{
		Content: "updated wow",
	}
	m, err := c.EditMessage(cID, mID, params)
	if err != nil {
		t.Fatal(err)
	}
	t.Log(m.Content)
}
<commit_msg>done channel_test.go<commit_after>package discgo_test

import (
	"github.com/nhooyr/discgo"
	"os"
	"testing"
)

var (
	cID   = "331307058660114433"
	mID   = "334104659767590912"
	emoji = "🍰"
)

func TestClient_GetChannelMessages(t *testing.T) {
	params := &discgo.MessagesGetParams{
		Limit: 5,
	}
	messages, err := c.Channel(cID).Messages().Get(params)
	if err != nil {
		t.Fatal(err)
	}
	t.Log(messages[0].Content)
}

func TestClient_CreateMessage(t *testing.T) {
	f, err := os.Open("/Users/poonam566/Desktop/screenshot.png")
	if err != nil {
		t.Fatal(err)
	}
	defer f.Close()

	params := &discgo.MessageCreateParams{
		Content: "boar",
		File: &discgo.File{
			Name:    "screenshot.png",
			Content: f,
		},
		Embed: &discgo.Embed{
			Description: "heads",
			Image: &discgo.EmbedImage{
				URL: "attachment://screenshot.png",
			},
		},
	}
	msg, err := c.Channel(cID).Messages().Create(params)
	if err != nil {
		t.Fatal(err)
	}
	t.Log(msg)
}

func TestClient_CreateReaction(t *testing.T) {
	err := c.Channel(cID).Message(mID).Reactions().Create(emoji)
	if err != nil {
		t.Fatal(err)
	}
}

func TestClient_DeleteReaction(t *testing.T) {
	err := c.Channel(cID).Message(mID).Reaction(emoji, "@me").Delete()
	if err != nil {
		t.Fatal(err)
	}
}

func TestClient_GetReactions(t *testing.T) {
	users, err := c.Channel(cID).Message(mID).Reactions().Get(emoji)
	if err != nil {
		t.Fatal(err)
	}
	t.Log(users[0].Username)
}

func TestClient_DeleteReactions(t *testing.T) {
	err := c.Channel(cID).Message(mID).Reactions().Delete()
	if err != nil {
		t.Fatal(err)
	}
}

func TestClient_UpdateMessage(t *testing.T) {
	params := &discgo.MessageEditParams{
		Content: "updated wow",
	}
	m, err := c.Channel(cID).Message(mID).Edit(params)
	if err != nil {
		t.Fatal(err)
	}
	t.Log(m.Content)
}
<|endoftext|>


<commit_before>package main

// charset_test.go

import (
	"testing"
	"strings"
	"errors"
)

// Extra example sets to test edge cases
var emptyset = charset{}
var negset = charset{'a': false}

// helper functions

// returns the something
func combinations(sets ...charset) []charset {
	combos := []charset{emptyset}

	// Builds up by doubling {∅} → {∅, X} -> {∅, X, Y, X∪Y} → ...
	for _, set := range sets {
		// Note that the length of combos is evaluated before the loop
		// So the new values are not iterated over
		for _, combo := range combos {
			combos = append(combos, union(set, combo))
		}
	}

	return combos
}

func allSets() []charset {
	return combinations(alphabet, digit, special, space, negset)
}

func allSetsNonEmpty() []charset {
	return combinations(alphabet, digit, special, space)[1:]
}

// testing getList function
// c ∈ getList(X) ⟺ c ∈ X
func TestGetList(t *testing.T) {

	sets := allSets()

	for _, set := range sets {
		list := getList(set)
		// c ∈ getList(X) ⟹ c ∈ X
		for _, x := range list {
			if !set[x] {
				t.Error(x, "found in", list, "but not in", set)
			}
		}
		// c ∈ X ⟹ c ∈ getList(X)
		for x, in := range set {
			if in {
				var err error
				list, err = remove(list, x)
				if err != nil {
					t.Error(x, "found in", set, "but not in", list, err)
				}
			}
		}
		// ∀c ∈ X . ∃! c ∈ getList(x)
		if len(list) != 0 {
			t.Error("Elements of", set, "repeated by getList. Expected empty list. Got", list)
		}
	}

}

// remove removes a sinlge element matching c from the list
func remove(list []rune, c rune) ([]rune, error) {
	before := len(list)
	list = []rune(strings.Replace(string(list), string(c), "", 1))
	after := len(list)
	if before != after + 1 {
		return list, errors.New("Removing '"+string(c)+"'did not shrink list")
	}
	return list, nil
}

// testing union function
// union() = ∅
func TestUnionNone(t *testing.T) {
	testEmpty := union()
	if len(testEmpty) != 0 {
		t.Error("union() should be empty, instead it is", testEmpty)
	}
}

// union(X) = X
func TestUnionOne(t *testing.T) {

	sets := allSets()

	for _, set := range sets {
		testSingle := union(set)
		if len(testSingle) != len(set) {
			t.Error("union(X) should be X, instead union(", set, ") is", testSingle)
		}
	}
}

// c ∈ union(X,Y) ⟺ c ∈ X ∪ Y
func TestUnionTwo(t *testing.T) {

	sets := allSets()

	for _, set1 := range sets {
		for _, set2 := range sets {
			uset := union(set1, set2)

			for element, in := range uset {
				if in && !set1[element] && !set2[element] {
					t.Error("'"+string(element)+"' in union but not either of the arguments")
					t.Log("X:", set1, "Y:", set2, "union(X,Y):", uset)
				}
			}
			for element, in := range set1 {
				if in && !uset[element] {
					t.Error("'"+string(element)+"' in first argument but not in union")
					t.Log("X:", set1, "Y:", set2, "union(X,Y):", uset)
				}
			}
			for element, in := range set2 {
				if in && !uset[element] {
					t.Error("'"+string(element)+"' in second argument but not in union")
					t.Log("X:", set1, "Y:", set2, "union(X,Y):", uset)
				}
			}
		}
	}

}

// c ∈ union([X0,..,Xn]...) ⟺ c ∈ ⋃{X_i}
func TestUnionMulti(t *testing.T) {
	sets := allSets()

	for _, set1 := range sets {
		for _, set2 := range sets {
			for _, set3 := range sets {
				uset := union(set1, set2, set3)

				for element, in := range uset {
					if in && !set1[element] && !set2[element] && !set3[element] {
						t.Error("'"+string(element)+"' in union but not the arguments")
						t.Log("X:", set1, "Y:", set2, "Z:", set3, "union(X,Y,Z):", uset)
					}
				}
				for element, in := range set1 {
					if in && !uset[element] {
						t.Error("'"+string(element)+"' in first argument but not in union")
						t.Log("X:", set1, "Y:", set2, "Z:", set3, "union(X,Y,Z):", uset)
					}
				}
				for element, in := range set2 {
					if in && !uset[element] {
						t.Error("'"+string(element)+"' in second argument but not in union")
						t.Log("X:", set1, "Y:", set2, "Z:", set3, "union(X,Y,Z):", uset)
					}
				}
				for element, in := range set3 {
					if in && !uset[element] {
						t.Error("'"+string(element)+"' in third argument but not in union")
						t.Log("X:", set1, "Y:", set2, "Z:", set3, "union(X,Y,Z):", uset)
					}
				}
			}
		}
	}
}

// testing valid function
// c ∈ valid(F) ⟺ charClass(c) ∈ F
func TestValid(t *testing.T) {
	t.Error("TestValid is not implemented")
}

// testing getCharSubsets function
// s ∈ getCharSubsets(str) ⟺ s ∩ str ≠ ∅
func TestGetCharSubsets(t *testing.T) {
	t.Error("TestGetCharSubsets is not implemented")
}
<commit_msg>Adds test for valid() function<commit_after>package main

// charset_test.go

import (
	"testing"
	"strings"
	"errors"
)

// Extra example sets to test edge cases
var emptyset = charset{}
var negset = charset{'a': false}

// helper functions

// returns the something
func combinations(sets ...charset) []charset {
	combos := []charset{emptyset}

	// Builds up by doubling {∅} → {∅, X} -> {∅, X, Y, X∪Y} → ...
	for _, set := range sets {
		// Note that the length of combos is evaluated before the loop
		// So the new values are not iterated over
		for _, combo := range combos {
			combos = append(combos, union(set, combo))
		}
	}

	return combos
}

func allSets() []charset {
	return combinations(alphabet, digit, special, space, negset)
}

func allSetsNonEmpty() []charset {
	return combinations(alphabet, digit, special, space)[1:]
}

// testing getList function
// c ∈ getList(X) ⟺ c ∈ X
func TestGetList(t *testing.T) {

	sets := allSets()

	for _, set := range sets {
		list := getList(set)
		// c ∈ getList(X) ⟹ c ∈ X
		for _, x := range list {
			if !set[x] {
				t.Error(x, "found in", list, "but not in", set)
			}
		}
		// c ∈ X ⟹ c ∈ getList(X)
		for x, in := range set {
			if in {
				var err error
				list, err = remove(list, x)
				if err != nil {
					t.Error(x, "found in", set, "but not in", list, err)
				}
			}
		}
		// ∀c ∈ X . ∃! c ∈ getList(x)
		if len(list) != 0 {
			t.Error("Elements of", set, "repeated by getList. Expected empty list. Got", list)
		}
	}

}

// remove removes a sinlge element matching c from the list
func remove(list []rune, c rune) ([]rune, error) {
	before := len(list)
	list = []rune(strings.Replace(string(list), string(c), "", 1))
	after := len(list)
	if before != after + 1 {
		return list, errors.New("Removing '"+string(c)+"'did not shrink list")
	}
	return list, nil
}

// testing union function
// union() = ∅
func TestUnionNone(t *testing.T) {
	testEmpty := union()
	if len(testEmpty) != 0 {
		t.Error("union() should be empty, instead it is", testEmpty)
	}
}

// union(X) = X
func TestUnionOne(t *testing.T) {

	sets := allSets()

	for _, set := range sets {
		testSingle := union(set)
		if len(testSingle) != len(set) {
			t.Error("union(X) should be X, instead union(", set, ") is", testSingle)
		}
	}
}

// c ∈ union(X,Y) ⟺ c ∈ X ∪ Y
func TestUnionTwo(t *testing.T) {

	sets := allSets()

	for _, set1 := range sets {
		for _, set2 := range sets {
			uset := union(set1, set2)

			for element, in := range uset {
				if in && !set1[element] && !set2[element] {
					t.Error("'"+string(element)+"' in union but not either of the arguments")
					t.Log("X:", set1, "Y:", set2, "union(X,Y):", uset)
				}
			}
			for element, in := range set1 {
				if in && !uset[element] {
					t.Error("'"+string(element)+"' in first argument but not in union")
					t.Log("X:", set1, "Y:", set2, "union(X,Y):", uset)
				}
			}
			for element, in := range set2 {
				if in && !uset[element] {
					t.Error("'"+string(element)+"' in second argument but not in union")
					t.Log("X:", set1, "Y:", set2, "union(X,Y):", uset)
				}
			}
		}
	}

}

// c ∈ union([X0,..,Xn]...) ⟺ c ∈ ⋃{X_i}
func TestUnionMulti(t *testing.T) {
	sets := allSets()

	for _, set1 := range sets {
		for _, set2 := range sets {
			for _, set3 := range sets {
				uset := union(set1, set2, set3)

				for element, in := range uset {
					if in && !set1[element] && !set2[element] && !set3[element] {
						t.Error("'"+string(element)+"' in union but not the arguments")
						t.Log("X:", set1, "Y:", set2, "Z:", set3, "union(X,Y,Z):", uset)
					}
				}
				for element, in := range set1 {
					if in && !uset[element] {
						t.Error("'"+string(element)+"' in first argument but not in union")
						t.Log("X:", set1, "Y:", set2, "Z:", set3, "union(X,Y,Z):", uset)
					}
				}
				for element, in := range set2 {
					if in && !uset[element] {
						t.Error("'"+string(element)+"' in second argument but not in union")
						t.Log("X:", set1, "Y:", set2, "Z:", set3, "union(X,Y,Z):", uset)
					}
				}
				for element, in := range set3 {
					if in && !uset[element] {
						t.Error("'"+string(element)+"' in third argument but not in union")
						t.Log("X:", set1, "Y:", set2, "Z:", set3, "union(X,Y,Z):", uset)
					}
				}
			}
		}
	}
}

// testing valid function
// c ∈ valid(charCombos) ⟺ charClass(c) ∈ charCombos
func TestValid(t *testing.T) {
	allCharCombos := allCharClasses()

	for _, charCombos := range allCharCombos {
		chars := valid(charCombos)
		// c ∈ valid(charCombos) ⟹ charClass(c) ∈ charCombos
		for c, in := range chars {
			if in {
				if !charCombos[charClass(c)] {
					t.Error("'"+string(c)+"' in valid(", charCombos,") =", chars, "but '"+string(c)+"' not in", charCombos)
				}
			}
		}
		// charClass(c) ∈ charCombos ⟹ c ∈ valid(charCombos)
		for class, in := range charCombos {
			if in {
				for c, in := range charsFrom[class] {
					if in {
						if !chars[c] {
							t.Error("'"+string(c)+"' not in valid(", charCombos,") =", chars, "but '"+string(c)+"' in", charCombos)
						}
					}
				}
			}
		}
	}
}

func allCharClasses() []map[string]bool {

	charclasses := []map[string]bool{}

	for i:=0; i < 16; i++ {
		a := map[string]bool{
			"alphabet": i >= 8,
			"digit":    i % 8 >= 4,
			"special":  i % 4 >= 2,
			"space":    i % 2 == 1,
		}
		charclasses = append(charclasses, a)
	}

	return charclasses
}

func charClass(c rune) string {
	switch {
	case alphabet[c]:
		return "alphabet"
	case digit[c]:
		return "digit"
	case special[c]:
		return "special"
	case space[c]:
		return "space"
	}
	return ""
}

// testing getCharSubsets function
// s ∈ getCharSubsets(str) ⟺ s ∩ str ≠ ∅
func TestGetCharSubsets(t *testing.T) {
	t.Error("TestGetCharSubsets is not implemented")
}
<|endoftext|>