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

package driver

/*

#cgo LDFLAGS: -llog

#include <android/log.h>
#include <jni.h>
#include <stdlib.h>

// __android_log_print(ANDROID_LOG_ERROR, "NativeCode", "foo", "bar");

static char* initAudioTrack(uintptr_t java_vm, uintptr_t jni_env,
    int sampleRate, int channelNum, int bytesPerSample, jobject* audioTrack, int* bufferSize) {
  *bufferSize = 0;
  JavaVM* vm = (JavaVM*)java_vm;
  JNIEnv* env = (JNIEnv*)jni_env;

  const jclass android_media_AudioFormat =
      (*env)->FindClass(env, "android/media/AudioFormat");
  const jclass android_media_AudioManager =
      (*env)->FindClass(env, "android/media/AudioManager");
  const jclass android_media_AudioTrack =
      (*env)->FindClass(env, "android/media/AudioTrack");

  const jint android_media_AudioManager_STREAM_MUSIC =
      (*env)->GetStaticIntField(
          env, android_media_AudioManager,
          (*env)->GetStaticFieldID(env, android_media_AudioManager, "STREAM_MUSIC", "I"));
  const jint android_media_AudioTrack_MODE_STREAM =
      (*env)->GetStaticIntField(
          env, android_media_AudioTrack,
          (*env)->GetStaticFieldID(env, android_media_AudioTrack, "MODE_STREAM", "I"));
  const jint android_media_AudioFormat_CHANNEL_OUT_MONO =
      (*env)->GetStaticIntField(
          env, android_media_AudioFormat,
          (*env)->GetStaticFieldID(env, android_media_AudioFormat, "CHANNEL_OUT_MONO", "I"));
  const jint android_media_AudioFormat_CHANNEL_OUT_STEREO =
      (*env)->GetStaticIntField(
          env, android_media_AudioFormat,
          (*env)->GetStaticFieldID(env, android_media_AudioFormat, "CHANNEL_OUT_STEREO", "I"));
  const jint android_media_AudioFormat_ENCODING_PCM_8BIT =
      (*env)->GetStaticIntField(
          env, android_media_AudioFormat,
          (*env)->GetStaticFieldID(env, android_media_AudioFormat, "ENCODING_PCM_8BIT", "I"));
  const jint android_media_AudioFormat_ENCODING_PCM_16BIT =
      (*env)->GetStaticIntField(
          env, android_media_AudioFormat,
          (*env)->GetStaticFieldID(env, android_media_AudioFormat, "ENCODING_PCM_16BIT", "I"));

  jint channel = android_media_AudioFormat_CHANNEL_OUT_MONO;
  switch (channelNum) {
  case 1:
    channel = android_media_AudioFormat_CHANNEL_OUT_MONO;
    break;
  case 2:
    channel = android_media_AudioFormat_CHANNEL_OUT_STEREO;
    break;
  default:
    return "invalid channel";
  }

  jint encoding = android_media_AudioFormat_ENCODING_PCM_8BIT;
  switch (bytesPerSample) {
  case 1:
    encoding = android_media_AudioFormat_ENCODING_PCM_8BIT;
    break;
  case 2:
    encoding = android_media_AudioFormat_ENCODING_PCM_16BIT;
    break;
  default:
    return "invalid bytesPerSample";
  }

  *bufferSize =
      (*env)->CallStaticIntMethod(
          env, android_media_AudioTrack,
          (*env)->GetStaticMethodID(env, android_media_AudioTrack, "getMinBufferSize", "(III)I"),
          sampleRate, channel, encoding);

  const jobject tmpAudioTrack =
      (*env)->NewObject(
          env, android_media_AudioTrack,
          (*env)->GetMethodID(env, android_media_AudioTrack, "<init>", "(IIIIII)V"),
          android_media_AudioManager_STREAM_MUSIC,
          sampleRate, channel, encoding, *bufferSize,
          android_media_AudioTrack_MODE_STREAM);
  // Note that *audioTrack will never be released.
  *audioTrack = (*env)->NewGlobalRef(env, tmpAudioTrack);

  (*env)->CallVoidMethod(
      env, *audioTrack,
      (*env)->GetMethodID(env, android_media_AudioTrack, "play", "()V"));

  return NULL;
}

static char* writeToAudioTrack(uintptr_t java_vm, uintptr_t jni_env,
    jobject audioTrack, int bytesPerSample, void* data, int length) {
  JavaVM* vm = (JavaVM*)java_vm;
  JNIEnv* env = (JNIEnv*)jni_env;

  const jclass android_media_AudioTrack =
      (*env)->FindClass(env, "android/media/AudioTrack");

  jbyteArray arrInBytes;
  jshortArray arrInShorts;
  switch (bytesPerSample) {
  case 1:
    arrInBytes = (*env)->NewByteArray(env, length);
    (*env)->SetByteArrayRegion(env, arrInBytes, 0, length, data);
    break;
  case 2:
    arrInShorts = (*env)->NewShortArray(env, length);
    (*env)->SetShortArrayRegion(env, arrInShorts, 0, length, data);
    break;
  }

  jint result;
  switch (bytesPerSample) {
  case 1:
    result =
        (*env)->CallIntMethod(
            env, audioTrack,
            (*env)->GetMethodID(env, android_media_AudioTrack, "write", "([BII)I"),
            arrInBytes, 0, length);
    break;
  case 2:
    result =
        (*env)->CallIntMethod(
            env, audioTrack,
            (*env)->GetMethodID(env, android_media_AudioTrack, "write", "([SII)I"),
            arrInShorts, 0, length);
    break;
  }

  switch (result) {
  case -3: // ERROR_INVALID_OPERATION
    return "invalid operation";
  case -2: // ERROR_BAD_VALUE
    return "bad value";
  case -1: // ERROR
    return "error";
  }
  if (result < 0) {
    return "unknown error";
  }
  return NULL;
}

*/
import "C"

import (
	"errors"
	"unsafe"

	"github.com/hajimehoshi/ebiten/internal/jni"
)

type Player struct {
	sampleRate     int
	channelNum     int
	bytesPerSample int
	audioTrack     C.jobject
	buffer         []byte
	bufferSize     int
	chErr          chan error
	chBuffer       chan []byte
}

func NewPlayer(sampleRate, channelNum, bytesPerSample int) (*Player, error) {
	p := &Player{
		sampleRate:     sampleRate,
		channelNum:     channelNum,
		bytesPerSample: bytesPerSample,
		buffer:         []byte{},
		chErr:          make(chan error),
		chBuffer:       make(chan []byte, 8),
	}
	if err := jni.RunOnJVM(func(vm, env, ctx uintptr) error {
		audioTrack := C.jobject(nil)
		bufferSize := C.int(0)
		if msg := C.initAudioTrack(C.uintptr_t(vm), C.uintptr_t(env),
			C.int(sampleRate), C.int(channelNum), C.int(bytesPerSample),
			&audioTrack, &bufferSize); msg != nil {
			return errors.New("driver: " + C.GoString(msg))
		}
		p.audioTrack = audioTrack
		p.bufferSize = int(bufferSize)
		return nil
	}); err != nil {
		return nil, err
	}
	go p.loop()
	return p, nil
}

func (p *Player) loop() {
	for bufInBytes := range p.chBuffer {
		var bufInShorts []int16
		if p.bytesPerSample == 2 {
			bufInShorts = make([]int16, len(bufInBytes)/2)
			for i := 0; i < len(bufInShorts); i++ {
				bufInShorts[i] = int16(bufInBytes[2*i]) | (int16(bufInBytes[2*i+1]) << 8)
			}
		}

		if err := jni.RunOnJVM(func(vm, env, ctx uintptr) error {
			msg := (*C.char)(nil)
			switch p.bytesPerSample {
			case 1:
				msg = C.writeToAudioTrack(C.uintptr_t(vm), C.uintptr_t(env),
					p.audioTrack, C.int(p.bytesPerSample),
					unsafe.Pointer(&bufInBytes[0]), C.int(len(bufInBytes)))
			case 2:
				msg = C.writeToAudioTrack(C.uintptr_t(vm), C.uintptr_t(env),
					p.audioTrack, C.int(p.bytesPerSample),
					unsafe.Pointer(&bufInShorts[0]), C.int(len(bufInShorts)))
			default:
				panic("not reach")
			}
			if msg != nil {
				return errors.New(C.GoString(msg))
			}
			return nil
		}); err != nil {
			p.chErr <- err
			return
		}
	}
}

func (p *Player) Proceed(data []byte) error {
	p.buffer = append(p.buffer, data...)
	if len(p.buffer) < p.bufferSize {
		return nil
	}
	buf := p.buffer[:p.bufferSize]
	select {
	case p.chBuffer <- buf:
	case err := <-p.chErr:
		return err
	}
	p.buffer = p.buffer[p.bufferSize:]
	return nil
}

func (p *Player) Close() error {
	return nil
}
<commit_msg>audio: Remove logger on Android<commit_after>// Copyright 2016 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package driver

/*

#include <jni.h>
#include <stdlib.h>

static char* initAudioTrack(uintptr_t java_vm, uintptr_t jni_env,
    int sampleRate, int channelNum, int bytesPerSample, jobject* audioTrack, int* bufferSize) {
  *bufferSize = 0;
  JavaVM* vm = (JavaVM*)java_vm;
  JNIEnv* env = (JNIEnv*)jni_env;

  const jclass android_media_AudioFormat =
      (*env)->FindClass(env, "android/media/AudioFormat");
  const jclass android_media_AudioManager =
      (*env)->FindClass(env, "android/media/AudioManager");
  const jclass android_media_AudioTrack =
      (*env)->FindClass(env, "android/media/AudioTrack");

  const jint android_media_AudioManager_STREAM_MUSIC =
      (*env)->GetStaticIntField(
          env, android_media_AudioManager,
          (*env)->GetStaticFieldID(env, android_media_AudioManager, "STREAM_MUSIC", "I"));
  const jint android_media_AudioTrack_MODE_STREAM =
      (*env)->GetStaticIntField(
          env, android_media_AudioTrack,
          (*env)->GetStaticFieldID(env, android_media_AudioTrack, "MODE_STREAM", "I"));
  const jint android_media_AudioFormat_CHANNEL_OUT_MONO =
      (*env)->GetStaticIntField(
          env, android_media_AudioFormat,
          (*env)->GetStaticFieldID(env, android_media_AudioFormat, "CHANNEL_OUT_MONO", "I"));
  const jint android_media_AudioFormat_CHANNEL_OUT_STEREO =
      (*env)->GetStaticIntField(
          env, android_media_AudioFormat,
          (*env)->GetStaticFieldID(env, android_media_AudioFormat, "CHANNEL_OUT_STEREO", "I"));
  const jint android_media_AudioFormat_ENCODING_PCM_8BIT =
      (*env)->GetStaticIntField(
          env, android_media_AudioFormat,
          (*env)->GetStaticFieldID(env, android_media_AudioFormat, "ENCODING_PCM_8BIT", "I"));
  const jint android_media_AudioFormat_ENCODING_PCM_16BIT =
      (*env)->GetStaticIntField(
          env, android_media_AudioFormat,
          (*env)->GetStaticFieldID(env, android_media_AudioFormat, "ENCODING_PCM_16BIT", "I"));

  jint channel = android_media_AudioFormat_CHANNEL_OUT_MONO;
  switch (channelNum) {
  case 1:
    channel = android_media_AudioFormat_CHANNEL_OUT_MONO;
    break;
  case 2:
    channel = android_media_AudioFormat_CHANNEL_OUT_STEREO;
    break;
  default:
    return "invalid channel";
  }

  jint encoding = android_media_AudioFormat_ENCODING_PCM_8BIT;
  switch (bytesPerSample) {
  case 1:
    encoding = android_media_AudioFormat_ENCODING_PCM_8BIT;
    break;
  case 2:
    encoding = android_media_AudioFormat_ENCODING_PCM_16BIT;
    break;
  default:
    return "invalid bytesPerSample";
  }

  *bufferSize =
      (*env)->CallStaticIntMethod(
          env, android_media_AudioTrack,
          (*env)->GetStaticMethodID(env, android_media_AudioTrack, "getMinBufferSize", "(III)I"),
          sampleRate, channel, encoding);

  const jobject tmpAudioTrack =
      (*env)->NewObject(
          env, android_media_AudioTrack,
          (*env)->GetMethodID(env, android_media_AudioTrack, "<init>", "(IIIIII)V"),
          android_media_AudioManager_STREAM_MUSIC,
          sampleRate, channel, encoding, *bufferSize,
          android_media_AudioTrack_MODE_STREAM);
  // Note that *audioTrack will never be released.
  *audioTrack = (*env)->NewGlobalRef(env, tmpAudioTrack);

  (*env)->CallVoidMethod(
      env, *audioTrack,
      (*env)->GetMethodID(env, android_media_AudioTrack, "play", "()V"));

  return NULL;
}

static char* writeToAudioTrack(uintptr_t java_vm, uintptr_t jni_env,
    jobject audioTrack, int bytesPerSample, void* data, int length) {
  JavaVM* vm = (JavaVM*)java_vm;
  JNIEnv* env = (JNIEnv*)jni_env;

  const jclass android_media_AudioTrack =
      (*env)->FindClass(env, "android/media/AudioTrack");

  jbyteArray arrInBytes;
  jshortArray arrInShorts;
  switch (bytesPerSample) {
  case 1:
    arrInBytes = (*env)->NewByteArray(env, length);
    (*env)->SetByteArrayRegion(env, arrInBytes, 0, length, data);
    break;
  case 2:
    arrInShorts = (*env)->NewShortArray(env, length);
    (*env)->SetShortArrayRegion(env, arrInShorts, 0, length, data);
    break;
  }

  jint result;
  switch (bytesPerSample) {
  case 1:
    result =
        (*env)->CallIntMethod(
            env, audioTrack,
            (*env)->GetMethodID(env, android_media_AudioTrack, "write", "([BII)I"),
            arrInBytes, 0, length);
    break;
  case 2:
    result =
        (*env)->CallIntMethod(
            env, audioTrack,
            (*env)->GetMethodID(env, android_media_AudioTrack, "write", "([SII)I"),
            arrInShorts, 0, length);
    break;
  }

  switch (result) {
  case -3: // ERROR_INVALID_OPERATION
    return "invalid operation";
  case -2: // ERROR_BAD_VALUE
    return "bad value";
  case -1: // ERROR
    return "error";
  }
  if (result < 0) {
    return "unknown error";
  }
  return NULL;
}

*/
import "C"

import (
	"errors"
	"unsafe"

	"github.com/hajimehoshi/ebiten/internal/jni"
)

type Player struct {
	sampleRate     int
	channelNum     int
	bytesPerSample int
	audioTrack     C.jobject
	buffer         []byte
	bufferSize     int
	chErr          chan error
	chBuffer       chan []byte
}

func NewPlayer(sampleRate, channelNum, bytesPerSample int) (*Player, error) {
	p := &Player{
		sampleRate:     sampleRate,
		channelNum:     channelNum,
		bytesPerSample: bytesPerSample,
		buffer:         []byte{},
		chErr:          make(chan error),
		chBuffer:       make(chan []byte, 8),
	}
	if err := jni.RunOnJVM(func(vm, env, ctx uintptr) error {
		audioTrack := C.jobject(nil)
		bufferSize := C.int(0)
		if msg := C.initAudioTrack(C.uintptr_t(vm), C.uintptr_t(env),
			C.int(sampleRate), C.int(channelNum), C.int(bytesPerSample),
			&audioTrack, &bufferSize); msg != nil {
			return errors.New("driver: " + C.GoString(msg))
		}
		p.audioTrack = audioTrack
		p.bufferSize = int(bufferSize)
		return nil
	}); err != nil {
		return nil, err
	}
	go p.loop()
	return p, nil
}

func (p *Player) loop() {
	for bufInBytes := range p.chBuffer {
		var bufInShorts []int16
		if p.bytesPerSample == 2 {
			bufInShorts = make([]int16, len(bufInBytes)/2)
			for i := 0; i < len(bufInShorts); i++ {
				bufInShorts[i] = int16(bufInBytes[2*i]) | (int16(bufInBytes[2*i+1]) << 8)
			}
		}

		if err := jni.RunOnJVM(func(vm, env, ctx uintptr) error {
			msg := (*C.char)(nil)
			switch p.bytesPerSample {
			case 1:
				msg = C.writeToAudioTrack(C.uintptr_t(vm), C.uintptr_t(env),
					p.audioTrack, C.int(p.bytesPerSample),
					unsafe.Pointer(&bufInBytes[0]), C.int(len(bufInBytes)))
			case 2:
				msg = C.writeToAudioTrack(C.uintptr_t(vm), C.uintptr_t(env),
					p.audioTrack, C.int(p.bytesPerSample),
					unsafe.Pointer(&bufInShorts[0]), C.int(len(bufInShorts)))
			default:
				panic("not reach")
			}
			if msg != nil {
				return errors.New(C.GoString(msg))
			}
			return nil
		}); err != nil {
			p.chErr <- err
			return
		}
	}
}

func (p *Player) Proceed(data []byte) error {
	p.buffer = append(p.buffer, data...)
	if len(p.buffer) < p.bufferSize {
		return nil
	}
	buf := p.buffer[:p.bufferSize]
	select {
	case p.chBuffer <- buf:
	case err := <-p.chErr:
		return err
	}
	p.buffer = p.buffer[p.bufferSize:]
	return nil
}

func (p *Player) Close() error {
	return nil
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"testing"

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

func TestAccAWSCodeDeployApp_basic(t *testing.T) {
	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSCodeDeployAppDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSCodeDeployApp,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSCodeDeployAppExists("aws_codedeploy_app.foo"),
				),
			},
			resource.TestStep{
				Config: testAccAWSCodeDeployAppModified,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSCodeDeployAppExists("aws_codedeploy_app.foo"),
				),
			},
		},
	})
}

func TestAccAWSCodeDeployApp_computePlatform(t *testing.T) {
	rName := acctest.RandString(5)

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSCodeDeployAppDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSCodeDeployAppConfigComputePlatform(rName, "Server"),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSCodeDeployAppExists("aws_codedeploy_app.foo"),
					resource.TestCheckResourceAttr(
						"aws_codedeploy_app.foo", "compute_platform", "Server"),
				),
			},
			resource.TestStep{
				Config: testAccAWSCodeDeployAppConfigComputePlatform(rName, "Lambda"),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSCodeDeployAppExists("aws_codedeploy_app.foo"),
					resource.TestCheckResourceAttr(
						"aws_codedeploy_app.foo", "compute_platform", "Lambda"),
				),
			},
		},
	})
}

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

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

		_, err := conn.GetApplication(&codedeploy.GetApplicationInput{
			ApplicationName: aws.String(rs.Primary.Attributes["name"]),
		})

		if err != nil {
			// Verify the error is what we want
			if ae, ok := err.(awserr.Error); ok && ae.Code() == "ApplicationDoesNotExistException" {
				continue
			}
			return err
		}

		return fmt.Errorf("still exists")
	}

	return nil
}

func testAccCheckAWSCodeDeployAppExists(name string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		_, ok := s.RootModule().Resources[name]
		if !ok {
			return fmt.Errorf("Not found: %s", name)
		}

		return nil
	}
}

func testAccAWSCodeDeployAppConfigComputePlatform(rName string, value string) string {
	return fmt.Sprintf(`
resource "aws_codedeploy_app" "foo" {
	name = "test-codedeploy-app-%s"
	compute_platform = "%s"
}`, rName, value)
}

var testAccAWSCodeDeployApp = `
resource "aws_codedeploy_app" "foo" {
	name = "foo"
}`

var testAccAWSCodeDeployAppModified = `
resource "aws_codedeploy_app" "foo" {
	name = "bar"
}`
<commit_msg>Test default value of `compute_platform`<commit_after>package aws

import (
	"fmt"
	"testing"

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

func TestAccAWSCodeDeployApp_basic(t *testing.T) {
	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSCodeDeployAppDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSCodeDeployApp,
				Check: resource.ComposeTestCheckFunc(
					resource.TestCheckResourceAttr("aws_codedeploy_app.foo", "compute_platform", "Server"),
					testAccCheckAWSCodeDeployAppExists("aws_codedeploy_app.foo"),
				),
			},
			resource.TestStep{
				Config: testAccAWSCodeDeployAppModified,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSCodeDeployAppExists("aws_codedeploy_app.foo"),
				),
			},
		},
	})
}

func TestAccAWSCodeDeployApp_computePlatform(t *testing.T) {
	rName := acctest.RandString(5)

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSCodeDeployAppDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSCodeDeployAppConfigComputePlatform(rName, "Server"),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSCodeDeployAppExists("aws_codedeploy_app.foo"),
					resource.TestCheckResourceAttr(
						"aws_codedeploy_app.foo", "compute_platform", "Server"),
				),
			},
			resource.TestStep{
				Config: testAccAWSCodeDeployAppConfigComputePlatform(rName, "Lambda"),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSCodeDeployAppExists("aws_codedeploy_app.foo"),
					resource.TestCheckResourceAttr(
						"aws_codedeploy_app.foo", "compute_platform", "Lambda"),
				),
			},
		},
	})
}

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

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

		_, err := conn.GetApplication(&codedeploy.GetApplicationInput{
			ApplicationName: aws.String(rs.Primary.Attributes["name"]),
		})

		if err != nil {
			// Verify the error is what we want
			if ae, ok := err.(awserr.Error); ok && ae.Code() == "ApplicationDoesNotExistException" {
				continue
			}
			return err
		}

		return fmt.Errorf("still exists")
	}

	return nil
}

func testAccCheckAWSCodeDeployAppExists(name string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		_, ok := s.RootModule().Resources[name]
		if !ok {
			return fmt.Errorf("Not found: %s", name)
		}

		return nil
	}
}

func testAccAWSCodeDeployAppConfigComputePlatform(rName string, value string) string {
	return fmt.Sprintf(`
resource "aws_codedeploy_app" "foo" {
	name = "test-codedeploy-app-%s"
	compute_platform = "%s"
}`, rName, value)
}

var testAccAWSCodeDeployApp = `
resource "aws_codedeploy_app" "foo" {
	name = "foo"
}`

var testAccAWSCodeDeployAppModified = `
resource "aws_codedeploy_app" "foo" {
	name = "bar"
}`
<|endoftext|>


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

package managedwriter

import (
	"context"
	"errors"
	"io"
	"time"

	"github.com/googleapis/gax-go/v2"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

type defaultRetryer struct {
	bo gax.Backoff
}

func (r *defaultRetryer) Retry(err error) (pause time.Duration, shouldRetry bool) {
	// TODO: refine this logic in a subsequent PR, there's some service-specific
	// retry predicates in addition to statuscode-based.
	s, ok := status.FromError(err)
	if !ok {
		// Treat context errors as non-retriable.
		if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
			return r.bo.Pause(), false
		}
		// Any other non-status based errors treated as retryable.
		return r.bo.Pause(), true
	}
	switch s.Code() {
	case codes.Unavailable:
		return r.bo.Pause(), true
	default:
		return r.bo.Pause(), false
	}
}

// shouldReconnect is akin to a retry predicate, in that it evaluates whether we should force
// our bidi stream to close/reopen based on the responses error.  Errors here signal that no
// further appends will succeed.
func shouldReconnect(err error) bool {
	var knownErrors = []error{
		io.EOF,
		status.Error(codes.Unavailable, "the connection is draining"), // errStreamDrain in gRPC transport
	}
	for _, ke := range knownErrors {
		if errors.Is(err, ke) {
			return true
		}
	}
	return false
}
<commit_msg>feat(bigquery/storage/managedwriter): define append retry predicate (#6650)<commit_after>// Copyright 2021 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.

package managedwriter

import (
	"context"
	"errors"
	"io"
	"strings"
	"time"

	"github.com/googleapis/gax-go/v2"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

var (
	defaultAppendRetries = 3
)

func newDefaultRetryer() *defaultRetryer {
	return &defaultRetryer{
		bigBo: gax.Backoff{
			Initial:    2 * time.Second,
			Multiplier: 5,
			Max:        5 * time.Minute,
		},
	}
}

type defaultRetryer struct {
	bo    gax.Backoff
	bigBo gax.Backoff // For more aggressive backoff, such as throughput quota
}

func (r *defaultRetryer) Retry(err error) (pause time.Duration, shouldRetry bool) {
	// This predicate evaluates errors for both enqueuing and reconnection.
	// See RetryAppend for retry that bounds attempts to a fixed number.
	s, ok := status.FromError(err)
	if !ok {
		// Treat context errors as non-retriable.
		if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
			return r.bo.Pause(), false
		}
		// EOF can happen in the case of connection close.
		if errors.Is(err, io.EOF) {
			return r.bo.Pause(), true
		}
		// Any other non-status based errors treated as retryable.
		return r.bo.Pause(), true
	}
	switch s.Code() {
	case codes.Aborted,
		codes.Canceled,
		codes.DeadlineExceeded,
		codes.Internal,
		codes.Unavailable:
		return r.bo.Pause(), true
	case codes.ResourceExhausted:
		if strings.HasPrefix(s.Message(), "Exceeds 'AppendRows throughput' quota") {
			// Note: internal b/246031522 opened to give this a structured error
			// and avoid string parsing.  Should be a QuotaFailure or similar.
			return r.bigBo.Pause(), true // more aggressive backoff
		}
	}
	return 0, false
}

// RetryAppend is a variation of the retry predicate that also bounds retries to a finite number of attempts.
func (r *defaultRetryer) RetryAppend(err error, attemptCount int) (pause time.Duration, shouldRetry bool) {

	if attemptCount > defaultAppendRetries {
		return 0, false // exceeded maximum retries.
	}
	return r.Retry(err)
}

// shouldReconnect is akin to a retry predicate, in that it evaluates whether we should force
// our bidi stream to close/reopen based on the responses error.  Errors here signal that no
// further appends will succeed.
func shouldReconnect(err error) bool {
	var knownErrors = []error{
		io.EOF,
		status.Error(codes.Unavailable, "the connection is draining"), // errStreamDrain in gRPC transport
	}
	for _, ke := range knownErrors {
		if errors.Is(err, ke) {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package params

import (
	"fmt"

	"github.com/runner-mei/gowbem"
)

func Value(name, value string) gowbem.CIMParamValue {
	return &gowbem.CimParamValue{
		Name:  name,
		Value: &gowbem.CimValue{Value: value},
	}
}

func LocalClassPath(name, namespaceName, className string) gowbem.CIMParamValue {
	names := gowbem.SplitNamespaces(namespaceName)
	namespaces := make([]gowbem.CimNamespace, len(names))
	for idx, name := range names {
		namespaces[idx].Name = name
	}

	return &gowbem.CimParamValue{
		Name: name,
		ValueReference: &gowbem.CimValueReference{
			LocalClassPath: &gowbem.CimLocalClassPath{
				NamespacePath: gowbem.CimLocalNamespacePath{Namespaces: namespaces},
				ClassName:     gowbem.CimClassName{Name: className},
			},
		},
	}
}

func ClassName(name, className string) gowbem.CIMParamValue {
	return &gowbem.CimParamValue{
		Name: name,
		ValueReference: &gowbem.CimValueReference{
			ClassName: &gowbem.CimClassName{Name: className},
		},
	}
}

func LocalInstancePath(name, namespaceName string, insName interface{}) gowbem.CIMParamValue {
	names := gowbem.SplitNamespaces(namespaceName)
	namespaces := make([]gowbem.CimNamespace, len(names))
	for idx, name := range names {
		namespaces[idx].Name = name
	}

	switch v := insName.(type) {
	case string:
		instanceName, e := gowbem.ParseInstanceName(v)
		if e != nil {
			panic(e)
		}
		return &gowbem.CimParamValue{
			Name: name,
			ValueReference: &gowbem.CimValueReference{
				LocalInstancePath: &gowbem.CimLocalInstancePath{
					LocalNamespacePath: gowbem.CimLocalNamespacePath{Namespaces: namespaces},
					InstanceName:       *instanceName,
				},
			},
		}

	case *gowbem.CimInstanceName:
		return &gowbem.CimParamValue{
			Name: name,
			ValueReference: &gowbem.CimValueReference{
				LocalInstancePath: &gowbem.CimLocalInstancePath{
					LocalNamespacePath: gowbem.CimLocalNamespacePath{Namespaces: namespaces},
					InstanceName:       *v,
				},
			},
		}

	case gowbem.CimInstanceName:
		return &gowbem.CimParamValue{
			Name: name,
			ValueReference: &gowbem.CimValueReference{
				LocalInstancePath: &gowbem.CimLocalInstancePath{
					LocalNamespacePath: gowbem.CimLocalNamespacePath{Namespaces: namespaces},
					InstanceName:       v,
				},
			},
		}

	default:
		panic(fmt.Errorf("unsupport type '%T' - %#v", insName, insName))
	}
}

func InstanceName(name string, insName interface{}) gowbem.CIMParamValue {
	switch v := insName.(type) {
	case string:
		instanceName, e := gowbem.ParseInstanceName(v)
		if e != nil {
			panic(e)
		}
		return &gowbem.CimParamValue{
			Name: name,
			ValueReference: &gowbem.CimValueReference{
				InstanceName: instanceName,
			},
		}

	case *gowbem.CimInstanceName:
		return &gowbem.CimParamValue{
			Name: name,
			ValueReference: &gowbem.CimValueReference{
				InstanceName: v,
			},
		}

	case gowbem.CimInstanceName:
		return &gowbem.CimParamValue{
			Name: name,
			ValueReference: &gowbem.CimValueReference{
				InstanceName: &v,
			},
		}

	default:
		panic(fmt.Errorf("unsupport type '%T' - %#v", insName, insName))
	}
}

// type CimValueReference struct {
//   XMLName           xml.Name              `xml:"VALUE.REFERENCE"`
//   ClassPath         *CimClassPath         `xml:"CLASSPATH,omitempty"`
//   LocalClassPath    *CimLocalClassPath    `xml:"LOCALCLASSPATH,omitempty"`
//   ClassName         *CimClassName         `xml:"CLASSNAME,omitempty"`
//   InstancePath      *CimInstancePath      `xml:"INSTANCEPATH,omitempty"`
//   LocalInstancePath *CimLocalInstancePath `xml:"LOCALINSTANCEPATH,omitempty"`
//   InstanceName      *CimInstanceName      `xml:"INSTANCENAME,omitempty"`
// }
<commit_msg>add params.Instance() and params.InstanceWithName()<commit_after>package params

import (
	"fmt"

	"github.com/runner-mei/gowbem"
)

func Value(name, value string) gowbem.CIMParamValue {
	return &gowbem.CimParamValue{
		Name:  name,
		Value: &gowbem.CimValue{Value: value},
	}
}

func ValueArray(name string, value []interface{}) gowbem.CIMParamValue {
	values := make([]gowbem.CimValueOrNull, 0, len(value))
	for idx := range value {
		if value[idx] == nil {
			values = append(values, gowbem.CimValueOrNull{Null: &gowbem.CimValueNull{}})
		} else {
			values = append(values, gowbem.CimValueOrNull{Value: &gowbem.CimValue{Value: fmt.Sprint(value)}})
		}
	}
	return &gowbem.CimParamValue{
		Name:       name,
		ValueArray: &gowbem.CimValueArray{Values: values},
	}
}

func ClassName(name, className string) gowbem.CIMParamValue {
	return &gowbem.CimParamValue{
		Name:      name,
		ClassName: &gowbem.CimClassName{Name: className},
	}
}

func InstanceName(name string, insName interface{}) gowbem.CIMParamValue {
	switch v := insName.(type) {
	case string:
		instanceName, e := gowbem.ParseInstanceName(v)
		if e != nil {
			panic(e)
		}
		return &gowbem.CimParamValue{
			Name:         name,
			InstanceName: instanceName,
		}

	case *gowbem.CimInstanceName:
		return &gowbem.CimParamValue{
			Name:         name,
			InstanceName: v,
		}

	case gowbem.CimInstanceName:
		return &gowbem.CimParamValue{
			Name:         name,
			InstanceName: &v,
		}

	default:
		panic(fmt.Errorf("unsupport type '%T' - %#v", insName, insName))
	}
}

func Instance(name string, instance gowbem.CIMInstance) gowbem.CIMParamValue {
	return &gowbem.CimParamValue{
		Name:     name,
		Instance: instance.(*gowbem.CimInstance),
	}
}

func InstanceWithName(name string, instance gowbem.CIMInstanceWithName) gowbem.CIMParamValue {
	return &gowbem.CimParamValue{
		Name:               name,
		ValueNamedInstance: instance.(*gowbem.CimValueNamedInstance),
	}
}

func LocalClassPathReference(name, namespaceName, className string) gowbem.CIMParamValue {
	names := gowbem.SplitNamespaces(namespaceName)
	namespaces := make([]gowbem.CimNamespace, len(names))
	for idx, name := range names {
		namespaces[idx].Name = name
	}

	return &gowbem.CimParamValue{
		Name: name,
		ValueReference: &gowbem.CimValueReference{
			LocalClassPath: &gowbem.CimLocalClassPath{
				NamespacePath: gowbem.CimLocalNamespacePath{Namespaces: namespaces},
				ClassName:     gowbem.CimClassName{Name: className},
			},
		},
	}
}

func ClassNameReference(name, className string) gowbem.CIMParamValue {
	return &gowbem.CimParamValue{
		Name: name,
		ValueReference: &gowbem.CimValueReference{
			ClassName: &gowbem.CimClassName{Name: className},
		},
	}
}

func LocalInstancePathReference(name, namespaceName string, insName interface{}) gowbem.CIMParamValue {
	names := gowbem.SplitNamespaces(namespaceName)
	namespaces := make([]gowbem.CimNamespace, len(names))
	for idx, name := range names {
		namespaces[idx].Name = name
	}

	switch v := insName.(type) {
	case string:
		instanceName, e := gowbem.ParseInstanceName(v)
		if e != nil {
			panic(e)
		}
		return &gowbem.CimParamValue{
			Name: name,
			ValueReference: &gowbem.CimValueReference{
				LocalInstancePath: &gowbem.CimLocalInstancePath{
					LocalNamespacePath: gowbem.CimLocalNamespacePath{Namespaces: namespaces},
					InstanceName:       *instanceName,
				},
			},
		}

	case *gowbem.CimInstanceName:
		return &gowbem.CimParamValue{
			Name: name,
			ValueReference: &gowbem.CimValueReference{
				LocalInstancePath: &gowbem.CimLocalInstancePath{
					LocalNamespacePath: gowbem.CimLocalNamespacePath{Namespaces: namespaces},
					InstanceName:       *v,
				},
			},
		}

	case gowbem.CimInstanceName:
		return &gowbem.CimParamValue{
			Name: name,
			ValueReference: &gowbem.CimValueReference{
				LocalInstancePath: &gowbem.CimLocalInstancePath{
					LocalNamespacePath: gowbem.CimLocalNamespacePath{Namespaces: namespaces},
					InstanceName:       v,
				},
			},
		}

	default:
		panic(fmt.Errorf("unsupport type '%T' - %#v", insName, insName))
	}
}

func InstanceNameReference(name string, insName interface{}) gowbem.CIMParamValue {
	switch v := insName.(type) {
	case string:
		instanceName, e := gowbem.ParseInstanceName(v)
		if e != nil {
			panic(e)
		}
		return &gowbem.CimParamValue{
			Name: name,
			ValueReference: &gowbem.CimValueReference{
				InstanceName: instanceName,
			},
		}

	case *gowbem.CimInstanceName:
		return &gowbem.CimParamValue{
			Name: name,
			ValueReference: &gowbem.CimValueReference{
				InstanceName: v,
			},
		}

	case gowbem.CimInstanceName:
		return &gowbem.CimParamValue{
			Name: name,
			ValueReference: &gowbem.CimValueReference{
				InstanceName: &v,
			},
		}

	default:
		panic(fmt.Errorf("unsupport type '%T' - %#v", insName, insName))
	}
}

// type CimValueReference struct {
//   XMLName           xml.Name              `xml:"VALUE.REFERENCE"`
//   ClassPath         *CimClassPath         `xml:"CLASSPATH,omitempty"`
//   LocalClassPath    *CimLocalClassPath    `xml:"LOCALCLASSPATH,omitempty"`
//   ClassName         *CimClassName         `xml:"CLASSNAME,omitempty"`
//   InstancePath      *CimInstancePath      `xml:"INSTANCEPATH,omitempty"`
//   LocalInstancePath *CimLocalInstancePath `xml:"LOCALINSTANCEPATH,omitempty"`
//   InstanceName      *CimInstanceName      `xml:"INSTANCENAME,omitempty"`
// }
<|endoftext|>


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

package linux_defaults

import (
	"time"
)

// Linux specific constants used in Linux datapath
const (
	// RouteTableIPSec is the default table ID to use for IPSec routing rules
	RouteTableIPSec = 200

	// RouteMarkDecrypt is the default route mark to use to indicate datapath
	// needs to decrypt a packet.
	RouteMarkDecrypt = 0x0D00

	// RouteMarkEncrypt is the default route mark to use to indicate datapath
	// needs to encrypt a packet.
	RouteMarkEncrypt = 0x0E00

	// RouteMarkMask is the mask required for the route mark value
	RouteMarkMask = 0xF00

	// MarkMultinodeNodeport is used for AWS ENI to mark traffic from
	// another node, so that it gets routed back through the relevant
	// interface.
	MarkMultinodeNodeport = 0x80

	// MaskMultinodeNodeport is the mask associated with the
	// RouterMarkNodePort
	MaskMultinodeNodeport = 0x80

	// IPSecProtocolID IP protocol ID for IPSec defined in RFC4303
	RouteProtocolIPSec = 50

	// RulePriorityIngress is the priority of the rule used for ingress routing
	// of endpoints. This priority is after encryption and proxy rules, and
	// before the local table priority.
	RulePriorityIngress = 20

	// RulePriorityEgress is the priority of the rule used for egress routing
	// of endpoints. This priority is after the local table priority.
	RulePriorityEgress = 110

	// RulePriorityNodeport is the priority of the rule used with AWS ENI to
	// make sure that lookups for multi-node NodePort traffic are NOT done
	// from the table for the VPC to which the endpoint's CIDR is
	// associated, but from the main routing table instead.
	// This priority is before the egress priority.
	RulePriorityNodeport = RulePriorityEgress - 1

	// TunnelDeviceName the default name of the tunnel device when using vxlan
	TunnelDeviceName = "cilium_vxlan"

	// IPSec offset value for node rules
	IPsecMaxKeyVersion = 16

	// IPsecMarkMask is the mask required for the IPsec SPI and encrypt/decrypt bits
	IPsecMarkMask = 0xFF00

	// IPsecMarkMaskIn is the mask required for IPsec to lookup encrypt/decrypt bits
	IPsecMarkMaskIn = 0x0F00

	// IPsecKeyDeleteDelay is the time to wait before removing old keys when
	// the IPsec key is changing.
	IPsecKeyDeleteDelay = 5 * time.Minute
)
<commit_msg>linux_defaults: Add RulePriorityEgressv2<commit_after>// Copyright 2019 Authors of Cilium
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package linux_defaults

import (
	"time"
)

// Linux specific constants used in Linux datapath
const (
	// RouteTableIPSec is the default table ID to use for IPSec routing rules
	RouteTableIPSec = 200

	// RouteMarkDecrypt is the default route mark to use to indicate datapath
	// needs to decrypt a packet.
	RouteMarkDecrypt = 0x0D00

	// RouteMarkEncrypt is the default route mark to use to indicate datapath
	// needs to encrypt a packet.
	RouteMarkEncrypt = 0x0E00

	// RouteMarkMask is the mask required for the route mark value
	RouteMarkMask = 0xF00

	// MarkMultinodeNodeport is used for AWS ENI to mark traffic from
	// another node, so that it gets routed back through the relevant
	// interface.
	MarkMultinodeNodeport = 0x80

	// MaskMultinodeNodeport is the mask associated with the
	// RouterMarkNodePort
	MaskMultinodeNodeport = 0x80

	// IPSecProtocolID IP protocol ID for IPSec defined in RFC4303
	RouteProtocolIPSec = 50

	// RulePriorityIngress is the priority of the rule used for ingress routing
	// of endpoints. This priority is after encryption and proxy rules, and
	// before the local table priority.
	RulePriorityIngress = 20

	// RulePriorityEgress is the priority of the rule used for egress routing
	// of endpoints. This priority is after the local table priority.
	RulePriorityEgress = 110

	// RulePriorityEgress is the v2 of the priority of the rule used for egress
	// routing of endpoints. This priority is after the local table priority.
	//
	// Because of https://github.com/cilium/cilium/issues/14336, we must use a
	// new priority value to disambiguate which rules are still under the old
	// scheme.
	RulePriorityEgressv2 = 111

	// RulePriorityNodeport is the priority of the rule used with AWS ENI to
	// make sure that lookups for multi-node NodePort traffic are NOT done
	// from the table for the VPC to which the endpoint's CIDR is
	// associated, but from the main routing table instead.
	// This priority is before the egress priority.
	RulePriorityNodeport = RulePriorityEgress - 1

	// TunnelDeviceName the default name of the tunnel device when using vxlan
	TunnelDeviceName = "cilium_vxlan"

	// IPSec offset value for node rules
	IPsecMaxKeyVersion = 16

	// IPsecMarkMask is the mask required for the IPsec SPI and encrypt/decrypt bits
	IPsecMarkMask = 0xFF00

	// IPsecMarkMaskIn is the mask required for IPsec to lookup encrypt/decrypt bits
	IPsecMarkMaskIn = 0x0F00

	// IPsecKeyDeleteDelay is the time to wait before removing old keys when
	// the IPsec key is changing.
	IPsecKeyDeleteDelay = 5 * time.Minute
)
<|endoftext|>


<commit_before>package sip

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"net/textproto"
	"sip/header"
	"strconv"
	"strings"
	"sync"
)

type StartLineWriter interface {
	StartLineWrite(io.Writer) error
}

type Message interface {
	StartLineWriter

	GetSIPVersion() string
	SetSIPVersion(string) error
	GetHeader() Header
	SetHeader(Header)
	GetContentLength() int64
	SetContentLength(l int64)
	GetBody() io.Reader
	SetBody(io.Reader)
	Write(io.Writer) error
}

////////////////////////////////////////////////////////////////////////////////
type message struct {
	StartLineWriter

	sipVersion string
	header     Header

	/** Direct accessors for frequently accessed headers  **/
	via           []*header.Via
	from          *header.From
	to            *header.To
	cSeq          *header.CSeq
	callId        *header.CallID
	maxForwards   *header.MaxForwards
	contentLength *header.ContentLength

	//contentLength int64
	body io.Reader
}

func (this *message) GetSIPVersion() string {
	return this.sipVersion
}

func (this *message) SetSIPVersion(s string) error {
	if s != "SIP/2.0" {
		return errors.New("Wrong SIP Version")
	} else {
		this.sipVersion = s
		return nil
	}
}

func (this *message) GetHeader() Header {
	return this.header
}

func (this *message) SetHeader(header Header) {
	this.header = header
}

func (this *message) GetContentLength() int64 {
	if this.contentLength != nil {
		return int64(this.contentLength.GetContentLength())
	} else {
		return 0
	}
}

func (this *message) SetContentLength(l int64) {
	if this.contentLength == nil {
		this.contentLength = header.NewContentLength()
	}
	this.contentLength.SetContentLength(int(l))
}

func (this *message) GetBody() io.Reader {
	return this.body
}

func (this *message) SetBody(body io.Reader) {
	this.body = body
}

// Headers that Request.Write handles itself and should be skipped.
var reqWriteExcludeHeader = map[string]bool{
	"Content-Length": true,
}

//  Start-Line
//	Header
//	ContentLength
//	Body
func (this *message) Write(w io.Writer) (err error) {
	var bw *bufio.Writer
	if _, ok := w.(io.ByteWriter); !ok {
		bw = bufio.NewWriter(w)
		w = bw
	}

	if err = this.StartLineWriter.StartLineWrite(w); err != nil {
		return err
	}

	if err = this.header.WriteSubset(w, reqWriteExcludeHeader); err != nil {
		return err
	}

	if _, err = fmt.Fprintf(w, "%s: %d\r\n", "Content-Length", this.GetContentLength()); err != nil {
		return err
	}

	if _, err = io.WriteString(w, "\r\n"); err != nil {
		return err
	}

	// Write body
	if this.body != nil {
		if _, err = io.Copy(w, io.LimitReader(this.body, this.GetContentLength())); err != nil {
			return err
		}
	}

	return nil
}

// ReadMessage reads and parses an incoming message from b.
func ReadMessage(b *bufio.Reader) (msg Message, err error) {
	tp := newTextprotoReader(b)

	// First line: INVITE sip:bob@biloxi.com SIP/2.0 or SIP/2.0 180 Ringing
	var s string
	if s, err = tp.ReadLine(); err != nil {
		return nil, err
	}
	defer func() {
		putTextprotoReader(tp)
		if err == io.EOF {
			err = io.ErrUnexpectedEOF
		}
	}()

	s1 := strings.Index(s, " ")
	s2 := strings.Index(s[s1+1:], " ")
	if s1 < 0 || s2 < 0 {
		return nil, fmt.Errorf("malformed SIP request %s", s)
	}
	s2 += s1 + 1

	if strings.TrimSpace(s[:s1]) == "SIP/2.0" {
		var statusCode int
		if statusCode, err = strconv.Atoi(s[s1+1 : s2]); err != nil {
			return nil, fmt.Errorf("malformed SIP status code %s", s[s1+1:s2])
		}
		sipVersion, reasonPhrase := s[:s1], s[s2+1:]
		if _, _, ok := ParseSIPVersion(sipVersion); !ok {
			return nil, fmt.Errorf("malformed SIP version", sipVersion)
		}
		msg = NewResponse(statusCode, reasonPhrase, nil)
	} else {
		method, requestURI, sipVersion := s[:s1], s[s1+1:s2], s[s2+1:]
		if _, _, ok := ParseSIPVersion(sipVersion); !ok {
			return nil, fmt.Errorf("malformed SIP version", sipVersion)
		}
		msg = NewRequest(method, requestURI, nil)
	}

	////////////////////////////////////////////////////////////////////////////
	// Subsequent lines: Key: value.
	mimeHeader, err := tp.ReadMIMEHeader()
	if err != nil {
		return nil, err
	}
	msg.SetHeader(Header(mimeHeader))

	////////////////////////////////////////////////////////////////////////////

	contentLens := msg.GetHeader()["Content-Length"]
	if len(contentLens) > 1 { // harden against SIP request smuggling. See RFC 7230.
		return nil, errors.New("http: message cannot contain multiple Content-Length headers")
	}

	// Logic based on Content-Length
	var cl string
	if len(contentLens) == 1 {
		cl = strings.TrimSpace(contentLens[0])
	}
	if cl != "" {
		n, err := parseContentLength(cl)
		if err != nil {
			return nil, err
		}
		msg.SetContentLength(n)
	} else {
		msg.GetHeader().Del("Content-Length")
		msg.SetContentLength(0)
	}

	////////////////////////////////////////////////////////////////////////////

	if msg.GetContentLength() > 0 {
		msg.SetBody(io.LimitReader(b, int64(msg.GetContentLength())))
	} else {
		msg.SetBody(nil)
	}

	return msg, nil
}

// parseContentLength trims whitespace from s and returns -1 if no value
// is set, or the value if it's >= 0.
func parseContentLength(cl string) (int64, error) {
	cl = strings.TrimSpace(cl)
	if cl == "" {
		return -1, nil
	}
	n, err := strconv.ParseInt(cl, 10, 64)
	if err != nil || n < 0 {
		return 0, fmt.Errorf("bad Content-Length %d", cl)
	}
	return n, nil

}

var textprotoReaderPool sync.Pool

func newTextprotoReader(br *bufio.Reader) *textproto.Reader {
	if v := textprotoReaderPool.Get(); v != nil {
		tr := v.(*textproto.Reader)
		tr.R = br
		return tr
	}
	return textproto.NewReader(br)
}

func putTextprotoReader(r *textproto.Reader) {
	r.R = nil
	textprotoReaderPool.Put(r)
}

// ParseSIPVersion parses a SIP version string.
// "SIP/2.0" returns (2, 0, true).
func ParseSIPVersion(vers string) (major, minor int, ok bool) {
	const Big = 1000000 // arbitrary upper bound
	switch vers {
	case "SIP/2.0":
		return 2, 0, true
	}
	if !strings.HasPrefix(vers, "SIP/") {
		return 0, 0, false
	}
	dot := strings.Index(vers, ".")
	if dot < 0 {
		return 0, 0, false
	}
	major, err := strconv.Atoi(vers[4:dot])
	if err != nil || major < 0 || major > Big {
		return 0, 0, false
	}
	minor, err = strconv.Atoi(vers[dot+1:])
	if err != nil || minor < 0 || minor > Big {
		return 0, 0, false
	}
	return major, minor, true
}
<commit_msg>remove old contentlength parser<commit_after>package sip

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"net/textproto"
	"sip/header"
	"sip/parser"
	"strconv"
	"strings"
	"sync"
)

type StartLineWriter interface {
	StartLineWrite(io.Writer) error
}

type Message interface {
	StartLineWriter

	GetSIPVersion() string
	SetSIPVersion(string) error
	GetHeader() Header
	SetHeader(Header)
	GetContentLength() int64
	SetContentLength(l int64)
	GetBody() io.Reader
	SetBody(io.Reader)
	Write(io.Writer) error
}

////////////////////////////////////////////////////////////////////////////////
type message struct {
	StartLineWriter

	sipVersion string
	header     Header

	/** Direct accessors for frequently accessed headers  **/
	via           []*header.Via
	from          *header.From
	to            *header.To
	cSeq          *header.CSeq
	callId        *header.CallID
	maxForwards   *header.MaxForwards
	contentLength *header.ContentLength

	//contentLength int64
	body io.Reader
}

func (this *message) GetSIPVersion() string {
	return this.sipVersion
}

func (this *message) SetSIPVersion(s string) error {
	if s != "SIP/2.0" {
		return errors.New("Wrong SIP Version")
	} else {
		this.sipVersion = s
		return nil
	}
}

func (this *message) GetHeader() Header {
	return this.header
}

func (this *message) SetHeader(header Header) {
	this.header = header
}

func (this *message) GetContentLength() int64 {
	if this.contentLength != nil {
		return int64(this.contentLength.GetContentLength())
	} else {
		return 0
	}
}

func (this *message) SetContentLength(l int64) {
	if this.contentLength == nil {
		this.contentLength = header.NewContentLength()
	}
	this.contentLength.SetContentLength(int(l))
}

func (this *message) GetBody() io.Reader {
	return this.body
}

func (this *message) SetBody(body io.Reader) {
	this.body = body
}

// Headers that Request.Write handles itself and should be skipped.
var reqWriteExcludeHeader = map[string]bool{
	"Content-Length": true,
}

//  Start-Line
//	Header
//	ContentLength
//	Body
func (this *message) Write(w io.Writer) (err error) {
	var bw *bufio.Writer
	if _, ok := w.(io.ByteWriter); !ok {
		bw = bufio.NewWriter(w)
		w = bw
	}

	if err = this.StartLineWriter.StartLineWrite(w); err != nil {
		return err
	}

	if err = this.header.WriteSubset(w, reqWriteExcludeHeader); err != nil {
		return err
	}

	if _, err = fmt.Fprintf(w, "%s: %d\r\n", "Content-Length", this.GetContentLength()); err != nil {
		return err
	}

	if _, err = io.WriteString(w, "\r\n"); err != nil {
		return err
	}

	// Write body
	if this.body != nil {
		if _, err = io.Copy(w, io.LimitReader(this.body, this.GetContentLength())); err != nil {
			return err
		}
	}

	return nil
}

// ReadMessage reads and parses an incoming message from b.
func ReadMessage(b *bufio.Reader) (msg Message, err error) {
	tp := newTextprotoReader(b)

	// First line: INVITE sip:bob@biloxi.com SIP/2.0 or SIP/2.0 180 Ringing
	var s string
	if s, err = tp.ReadLine(); err != nil {
		return nil, err
	}
	defer func() {
		putTextprotoReader(tp)
		if err == io.EOF {
			err = io.ErrUnexpectedEOF
		}
	}()

	s1 := strings.Index(s, " ")
	s2 := strings.Index(s[s1+1:], " ")
	if s1 < 0 || s2 < 0 {
		return nil, fmt.Errorf("malformed SIP request %s", s)
	}
	s2 += s1 + 1

	if strings.TrimSpace(s[:s1]) == "SIP/2.0" {
		var statusCode int
		if statusCode, err = strconv.Atoi(s[s1+1 : s2]); err != nil {
			return nil, fmt.Errorf("malformed SIP status code %s", s[s1+1:s2])
		}
		sipVersion, reasonPhrase := s[:s1], s[s2+1:]
		if _, _, ok := ParseSIPVersion(sipVersion); !ok {
			return nil, fmt.Errorf("malformed SIP version", sipVersion)
		}
		msg = NewResponse(statusCode, reasonPhrase, nil)
	} else {
		method, requestURI, sipVersion := s[:s1], s[s1+1:s2], s[s2+1:]
		if _, _, ok := ParseSIPVersion(sipVersion); !ok {
			return nil, fmt.Errorf("malformed SIP version", sipVersion)
		}
		msg = NewRequest(method, requestURI, nil)
	}

	////////////////////////////////////////////////////////////////////////////
	// Subsequent lines: Key: value.
	mimeHeader, err := tp.ReadMIMEHeader()
	if err != nil {
		return nil, err
	}
	msg.SetHeader(Header(mimeHeader))

	////////////////////////////////////////////////////////////////////////////

	contentLens := msg.GetHeader()["Content-Length"]
	if len(contentLens) > 1 { // harden against SIP request smuggling. See RFC 7230.
		return nil, errors.New("http: message cannot contain multiple Content-Length headers")
	} else if len(contentLens) == 0 {
		msg.SetContentLength(0)
	} else {
		if cl, err := parser.NewContentLengthParser("Content-Length: " + contentLens[0]).Parse(); err != nil {
			return nil, err
		} else {
			msg.SetContentLength(int64(cl.(header.ContentLengthHeader).GetContentLength()))
		}
	}

	////////////////////////////////////////////////////////////////////////////

	if msg.GetContentLength() > 0 {
		msg.SetBody(io.LimitReader(b, int64(msg.GetContentLength())))
	} else {
		msg.SetBody(nil)
	}

	return msg, nil
}

var textprotoReaderPool sync.Pool

func newTextprotoReader(br *bufio.Reader) *textproto.Reader {
	if v := textprotoReaderPool.Get(); v != nil {
		tr := v.(*textproto.Reader)
		tr.R = br
		return tr
	}
	return textproto.NewReader(br)
}

func putTextprotoReader(r *textproto.Reader) {
	r.R = nil
	textprotoReaderPool.Put(r)
}

// ParseSIPVersion parses a SIP version string.
// "SIP/2.0" returns (2, 0, true).
func ParseSIPVersion(vers string) (major, minor int, ok bool) {
	const Big = 1000000 // arbitrary upper bound
	switch vers {
	case "SIP/2.0":
		return 2, 0, true
	}
	if !strings.HasPrefix(vers, "SIP/") {
		return 0, 0, false
	}
	dot := strings.Index(vers, ".")
	if dot < 0 {
		return 0, 0, false
	}
	major, err := strconv.Atoi(vers[4:dot])
	if err != nil || major < 0 || major > Big {
		return 0, 0, false
	}
	minor, err = strconv.Atoi(vers[dot+1:])
	if err != nil || minor < 0 || minor > Big {
		return 0, 0, false
	}
	return major, minor, true
}
<|endoftext|>


<commit_before>package pconn

import (
	"log"
	"time"

	"github.com/gorilla/websocket"
	"github.com/msbu-tech/go-pconn/msg"
	"github.com/satori/go.uuid"
)

//连接定义
type Pconn struct {
	rid             string          //请求id
	cuid            string          //uid
	uuid            string          //server端生成的唯一id
	timestamp       int64           //建连时间戳
	closed          bool            //连接是否关闭
	connected       bool            //是否已经建立连接（客户端是否已经发送connect命令）
	hub             *MyHub          //连接所在的HUB
	c               *websocket.Conn //链接的ws指针
	connectedTimer  *time.Timer     //连接计时器，用于关闭超时未发送connect的连接
	connTimeoutChan chan bool
	pushChan chan *msg.PushMsg
	closeChan chan bool
	cmdChan chan *msg.ClientMsg
}

//新建连接，一般由Hub接收到连接请求时发起
func New(h *MyHub, conn *websocket.Conn) *Pconn {
	c := Pconn{
		rid:             uuid.NewV4().String(),
		hub:             h,
		c:               conn,
		timestamp:       time.Now().Unix(),
		uuid : uuid.NewV1().String(),
		closed:          false,
		connected:       false,
		connTimeoutChan: make(chan bool),
		pushChan:        make(chan *msg.PushMsg),
		closeChan:       make(chan bool),
		cmdChan:         make(chan *msg.ClientMsg),
	}
	go c.read()
	go c.processChan()

	//设置客户端未连接超时，用于清理建连接后未发请求的连接
	if true {
		c.connectedTimer = time.AfterFunc(10*time.Second, c.connectTimeout)
	}

	return &c
}

//请求主循环，监听ws的消息
func (c *Pconn) read() {
	for {
		_, message, err := c.c.ReadMessage()
		if err != nil {
			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
				log.Printf("error: %v", err)
			}
			c.closeChan <- true
            break
		}
		log.Printf("recv: %s", message)
		clientMsg := new(msg.ClientMsg)
		err = msg.NewClientMsg(string(message), clientMsg)
		if err != nil{
			log.Printf("client message parse error, msg: %s", clientMsg)
			continue
		}
		err = c.dispatchCmd(clientMsg)
		if err != nil{
			log.Printf("client message dispatch error, error: %s", err)
		}
	}
}

func (c *Pconn) dispatchCmd(cMsg *msg.ClientMsg) error  {
	switch cMsg.GetCmd() {
	case "connect":
		c.connectCmd(cMsg)
	case "disconnect":
		c.disconnectCmd(cMsg)
	case "message":
		c.messageCmd(cMsg)
	}
	return nil
}

func (c *Pconn) connectCmd(cMsg *msg.ClientMsg)  {
	c.cmdChan <- cMsg
}

func (c *Pconn) disconnectCmd(cMsg *msg.ClientMsg)  {
	c.cmdChan <- cMsg
}

func (c *Pconn) messageCmd(cMsg *msg.ClientMsg)  {
	c.cmdChan <- cMsg
}

func (c *Pconn) processChan()  {
	for {
		select {
		case <-c.connTimeoutChan:
			if !c.connected && !c.closed {
				c.disconnect()
				log.Printf("connenction timeout, goroutine exit, rid: %s", c.rid)
				return
			}
		case <- c.closeChan:
			c.disconnect()
			return
		case message := <- c.pushChan:
			c.push(message)
		case cMsg := <- c.cmdChan:
			switch cMsg.GetCmd() {
			case Connect:
				c.connect(cMsg.GetCuid())
			case Disconnect:
				c.disconnect()
			case Message:
                //TODO 解析msg，连接后端，转发请求
				log.Printf("got client message: %s", cMsg.GetBody())
            default:
                log.Printf("unknown cmd: %s", cMsg.GetCmd())
			}
		}
	}
}

func (c *Pconn) Push(messageStr string) {
	message := new(msg.PushMsg)
	message.SetContent(messageStr)
	c.pushChan <- message
}

func (c *Pconn) push(message *msg.PushMsg) error {
	messageStr := message.ToString()
	err := c.c.WriteMessage(websocket.TextMessage, []byte(messageStr))
	if err != nil {
		log.Println("write error:", err)
		return err
	}
	return nil
}

func (c *Pconn) connect(cuid string) error {
	if !c.connected{
		c.cuid = cuid
		err := c.hub.AddPconn(c.cuid, c)
		if err != nil {
			log.Println("connect error:", err)
			return err
		}
		log.Printf("conn %s connected", c.cuid)
		c.connected = true
	}
	return nil
}

func (c *Pconn) disconnect() error {
	err := c.c.Close()
	log.Println("close ws connnection")
	if err != nil {
		log.Println("disconnect error[ws close]:", err)
		return err
	}
	err = c.hub.DelPconn(c.cuid)
	if err != nil {
		log.Println("disconnect error[RemoveConn]:", err)
		return err
	}
	c.closed = true

	log.Printf("disconnect link, rid: %s", c.rid)
	return nil
}

func (c *Pconn) connectTimeout() {
	c.connTimeoutChan <- true
}
<commit_msg>fix double close bug<commit_after>package pconn

import (
	"log"
	"time"

	"github.com/gorilla/websocket"
	"github.com/msbu-tech/go-pconn/msg"
	"github.com/satori/go.uuid"
)

//连接定义
type Pconn struct {
	rid             string          //请求id
	cuid            string          //uid
	uuid            string          //server端生成的唯一id
	timestamp       int64           //建连时间戳
	closed          bool            //连接是否关闭
	connected       bool            //是否已经建立连接（客户端是否已经发送connect命令）
	hub             *MyHub          //连接所在的HUB
	c               *websocket.Conn //链接的ws指针
	connectedTimer  *time.Timer     //连接计时器，用于关闭超时未发送connect的连接
	connTimeoutChan chan bool
	pushChan chan *msg.PushMsg
	closeChan chan bool
	cmdChan chan *msg.ClientMsg
}

//新建连接，一般由Hub接收到连接请求时发起
func New(h *MyHub, conn *websocket.Conn) *Pconn {
	c := Pconn{
		rid:             uuid.NewV4().String(),
		hub:             h,
		c:               conn,
		timestamp:       time.Now().Unix(),
		uuid : uuid.NewV1().String(),
		closed:          false,
		connected:       false,
		connTimeoutChan: make(chan bool),
		pushChan:        make(chan *msg.PushMsg),
		closeChan:       make(chan bool),
		cmdChan:         make(chan *msg.ClientMsg),
	}
	go c.read()
	go c.processChan()

	//设置客户端未连接超时，用于清理建连接后未发请求的连接
	if true {
		c.connectedTimer = time.AfterFunc(10*time.Second, c.connectTimeout)
	}

	return &c
}

//请求主循环，监听ws的消息
func (c *Pconn) read() {
	for {
		_, message, err := c.c.ReadMessage()
		if err != nil {
			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
				log.Printf("error: %v", err)
			}
			c.closeChan <- true
            break
		}
		log.Printf("recv: %s", message)
		clientMsg := new(msg.ClientMsg)
		err = msg.NewClientMsg(string(message), clientMsg)
		if err != nil{
			log.Printf("client message parse error, msg: %s", clientMsg)
			continue
		}
		err = c.dispatchCmd(clientMsg)
		if err != nil{
			log.Printf("client message dispatch error, error: %s", err)
		}
	}
}

func (c *Pconn) dispatchCmd(cMsg *msg.ClientMsg) error  {
	switch cMsg.GetCmd() {
	case "connect":
		c.connectCmd(cMsg)
	case "disconnect":
		c.disconnectCmd(cMsg)
	case "message":
		c.messageCmd(cMsg)
	}
	return nil
}

func (c *Pconn) connectCmd(cMsg *msg.ClientMsg)  {
	c.cmdChan <- cMsg
}

func (c *Pconn) disconnectCmd(cMsg *msg.ClientMsg)  {
	c.cmdChan <- cMsg
}

func (c *Pconn) messageCmd(cMsg *msg.ClientMsg)  {
	c.cmdChan <- cMsg
}

func (c *Pconn) processChan()  {
	for {
		select {
		case <-c.connTimeoutChan:
			if !c.connected && !c.closed {
				c.disconnect()
				log.Printf("connenction timeout, goroutine exit, rid: %s", c.rid)
				return
			}
		case <- c.closeChan:
			c.disconnect()
			return
		case message := <- c.pushChan:
			c.push(message)
		case cMsg := <- c.cmdChan:
			switch cMsg.GetCmd() {
			case Connect:
				c.connect(cMsg.GetCuid())
			case Disconnect:
				c.disconnect()
                return
			case Message:
                //TODO 解析msg，连接后端，转发请求
				log.Printf("got client message: %s", cMsg.GetBody())
            default:
                log.Printf("unknown cmd: %s", cMsg.GetCmd())
			}
		}
	}
}

func (c *Pconn) Push(messageStr string) {
	message := new(msg.PushMsg)
	message.SetContent(messageStr)
	c.pushChan <- message
}

func (c *Pconn) push(message *msg.PushMsg) error {
	messageStr := message.ToString()
	err := c.c.WriteMessage(websocket.TextMessage, []byte(messageStr))
	if err != nil {
		log.Println("write error:", err)
		return err
	}
	return nil
}

func (c *Pconn) connect(cuid string) error {
	if !c.connected{
		c.cuid = cuid
		err := c.hub.AddPconn(c.cuid, c)
		if err != nil {
			log.Println("connect error:", err)
			return err
		}
		log.Printf("conn %s connected", c.cuid)
		c.connected = true
	}
	return nil
}

func (c *Pconn) disconnect() error {
	err := c.c.Close()
	log.Println("close ws connnection")
	if err != nil {
		log.Println("disconnect error[ws close]:", err)
		return err
	}
	err = c.hub.DelPconn(c.cuid)
	if err != nil {
		log.Println("disconnect error[RemoveConn]:", err)
		return err
	}
	c.closed = true

	log.Printf("disconnect link, rid: %s", c.rid)
	return nil
}

func (c *Pconn) connectTimeout() {
	c.connTimeoutChan <- true
}
<|endoftext|>


<commit_before>package gocube

// A Phase1Axis represents the y-axis corner orientations, ZZ edge orientations,
// and the permutation of the E slice.
type Phase1Axis struct {
	CornerOrientations int
	EdgeOrientations   int
	SlicePerm          int
}

// A Phase1Cube is an efficient way to represent the parts of a cube which
// matter for the first phase of Kociemba's algorithm.
// The FB edge orientation can be used for both Y and X phase-1 goals, and the
// UD edge orientation can be used for the Z phase-1 goal. Thus, no RL edge
// orientations are needed.
type Phase1Cube struct {
	XCornerOrientation int
	YCornerOrientation int
	ZCornerOrientation int

	FBEdgeOrientation int
	UDEdgeOrientation int

	ESlicePermutation int
	SSlicePermutation int
	MSlicePermutation int
}

// Move applies a move on a Phase1Cube using a moves table.
func (p *Phase1Cube) Move(m Move, table *Phase1Moves) {
	// TODO: apply the move to each axis of the represented data.
}

// Phase1Moves is a table containing the necessary data to efficiently perform
// moves on a Phase1Cube.
// Note that only one move table is needed for all 3 axes (i.e. all three
// phase-1 goals). Thus, the move tables apply directly to the Y-oriented
// phase-1 goal. Moves much be translated for the X-oriented and Z-oriented
// goals.
type Phase1Moves struct {
	ESliceMoves [495][18]int
	EOMoves [2048][18]int
	COMoves [2048][18]int
}

// NewPhase1Moves generates tables for applying phase-1 moves.
func NewPhase1Moves() *Phase1Moves {
	res := &Phase1Moves{}

	// TODO: generate the E-slice moves
	// TODO: generate the EO moves
	// TODO: generate the CO moves

	return res
}
<commit_msg>generate EO moves<commit_after>package gocube

// A Phase1Axis represents the y-axis corner orientations, ZZ edge orientations,
// and the permutation of the E slice.
type Phase1Axis struct {
	CornerOrientations int
	EdgeOrientations   int
	SlicePerm          int
}

// A Phase1Cube is an efficient way to represent the parts of a cube which
// matter for the first phase of Kociemba's algorithm.
// The FB edge orientation can be used for both Y and X phase-1 goals, and the
// UD edge orientation can be used for the Z phase-1 goal. Thus, no RL edge
// orientations are needed.
type Phase1Cube struct {
	XCornerOrientation int
	YCornerOrientation int
	ZCornerOrientation int

	FBEdgeOrientation int
	UDEdgeOrientation int

	ESlicePermutation int
	SSlicePermutation int
	MSlicePermutation int
}

// Move applies a move on a Phase1Cube using a moves table.
func (p *Phase1Cube) Move(m Move, table *Phase1Moves) {
	// TODO: apply the move to each axis of the represented data.
}

// Phase1Moves is a table containing the necessary data to efficiently perform
// moves on a Phase1Cube.
// Note that only one move table is needed for all 3 axes (i.e. all three
// phase-1 goals). Thus, the move tables apply directly to the Y-oriented
// phase-1 goal. Moves much be translated for the X-oriented and Z-oriented
// goals.
type Phase1Moves struct {
	ESliceMoves [495][18]int
	EOMoves [2048][18]int
	COMoves [2048][18]int
}

// NewPhase1Moves generates tables for applying phase-1 moves.
func NewPhase1Moves() *Phase1Moves {
	res := &Phase1Moves{}

	// TODO: generate the E-slice moves
	// TODO: generate the CO moves

	// Generate the EO cases and do moves on them.
	for i := 0; i < 2048; i++ {
		// Generate a CubieEdges object for this EO case.
		edges := SolvedCubieEdges()
		parity := false
		for x := 0; x < 11; x++ {
			if (i & (1 << x)) != 0 {
				parity = !parity
				edges[x].Flip = true
			}
		}
		edges[11].Flip = parity

		// Apply each move and encode the result.
		for m := 0; m < 18; m++ {
			aCase := edges
			aCase.Move(Move(m))
			res.EOMoves[i][m] = encodeEO(&aCase)
		}
	}

	return res
}

func encodeEO(c *CubieEdges) int {
	res := 0
	for i := 0; i < 11; i++ {
		if (*c)[i].Flip {
			res |= (1 << i)
		}
	}
	return res
}
<|endoftext|>


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

package pkcs11

// These t depend on SoftHSM and the library being in
// in /usr/lib/softhsm/libsofthsm.so

import (
	"fmt"
	"math/big"
	"os"
	"testing"
)

func setenv() *Ctx {
	wd, _ := os.Getwd()
	os.Setenv("SOFTHSM_CONF", wd+"/softhsm.conf")
	p := New("/usr/lib/softhsm/libsofthsm.so")
	// Debug lib
	// p := New("/home/miek/libsofthsm.so")
	return p
}

func getSession(p *Ctx, t *testing.T) SessionHandle {
	if e := p.Initialize(); e != nil {
		t.Fatalf("init error %s\n", e.Error())
	}
	slots, e := p.GetSlotList(true)
	if e != nil {
		t.Fatalf("slots %s\n", e.Error())
	}
	session, e := p.OpenSession(slots[0], CKF_SERIAL_SESSION)
	if e != nil {
		t.Fatalf("session %s\n", e.Error())
	}
	if e := p.Login(session, CKU_USER, "1234"); e != nil {
		t.Fatal("user pin %s\n", e.Error())
	}
	return session
}

func TestGetInfo(t *testing.T) {
	p := setenv()
	session := getSession(p, t)
	defer p.Logout(session)
	defer p.CloseSession(session)
	defer p.Finalize()
	defer p.Destroy()
	info, err := p.GetInfo()
	if err != nil {
		t.Fatalf("Non zero error %s\n", err.Error())
	}
	if info.ManufacturerID != "SoftHSM" {
		t.Fatal("ID should be SoftHSM")
	}
	t.Logf("%+v\n", info)
}

func TestObjectFinding(t *testing.T) {
	p := setenv()
	session := getSession(p, t)
	defer p.Logout(session)
	defer p.CloseSession(session)
	defer p.Finalize()
	defer p.Destroy()
	// There are 2 keys in the db with this tag
	template := []*Attribute{NewAttribute(CKA_LABEL, "MyFirstKey")}
	if e := p.FindObjectsInit(session, template); e != nil {
		t.Fatalf("Failed to init: %s\n", e.Error())
	}
	obj, b, e := p.FindObjects(session, 2)
	if e != nil {
		t.Fatalf("Failed to find: %s %v\n", e.Error(), b)
	}
	if e := p.FindObjectsFinal(session); e != nil {
		t.Fatalf("Failed to finalize: %s\n", e.Error())
	}
	if len(obj) != 2 {
		t.Fatal("should have found two objects")
	}
}

func TestGetAttributeValue(t *testing.T) {
	p := setenv()
	session := getSession(p, t)
	defer p.Logout(session)
	defer p.Destroy()
	defer p.Finalize()
	defer p.CloseSession(session)
	// There are at least two RSA keys in the hsm.db, objecthandle 1 and 2.
	template := []*Attribute{
		NewAttribute(CKA_PUBLIC_EXPONENT, nil),
		NewAttribute(CKA_MODULUS_BITS, nil),
		NewAttribute(CKA_MODULUS, nil),
		NewAttribute(CKA_LABEL, nil),
	}
	// ObjectHandle two is the public key
	attr, err := p.GetAttributeValue(session, ObjectHandle(2), template)
	if err != nil {
		t.Fatalf("err %s\n", err.Error())
	}
	for i, a := range attr {
		t.Logf("Attr %d, type %d, valuelen %d", i, a.Type, len(a.Value))
		if a.Type == CKA_MODULUS {
			mod := big.NewInt(0)
			mod.SetBytes(a.Value)
			t.Logf("Modulus %s\n", mod.String())
		}
	}
}

func TestDigest(t *testing.T) {
	p := setenv()
	session := getSession(p, t)
	defer p.Logout(session)
	defer p.CloseSession(session)
	defer p.Finalize()
	defer p.Destroy()
	e := p.DigestInit(session, []*Mechanism{NewMechanism(CKM_SHA_1, nil)})
	if e != nil {
		t.Fatalf("DigestInit: %s\n", e.Error())
	}

	hash, e := p.Digest(session, []byte("this is a string"))
	if e != nil {
		t.Fatalf("Digest: %s\n", e.Error())
	}
	hex := ""
	for _, d := range hash {
		hex += fmt.Sprintf("%x", d)
	}
	// Teststring create with: echo -n "this is a string" | sha1sum
	if hex != "517592df8fec3ad146a79a9af153db2a4d784ec5" {
		t.Fatalf("wrong digest: %s", hex)
	}
}

func TestDigestUpdate(t *testing.T) {
	p := setenv()
	session := getSession(p, t)
	defer p.Logout(session)
	defer p.CloseSession(session)
	defer p.Finalize()
	defer p.Destroy()
	if e := p.DigestInit(session, []*Mechanism{NewMechanism(CKM_SHA_1, nil)}); e != nil {
		t.Fatalf("DigestInit: %s\n", e.Error())
	}
	if e := p.DigestUpdate(session, []byte("this is ")); e != nil {
		t.Fatalf("DigestUpdate: %s\n", e.Error())
	}
	if e := p.DigestUpdate(session, []byte("a string")); e != nil {
		t.Fatalf("DigestUpdate: %s\n", e.Error())
	}
	hash, e := p.DigestFinal(session)
	if e != nil {
		t.Fatalf("DigestFinal: %s\n", e.Error())
	}
	hex := ""
	for _, d := range hash {
		hex += fmt.Sprintf("%x", d)
	}
	// Teststring create with: echo -n "this is a string" | sha1sum
	if hex != "517592df8fec3ad146a79a9af153db2a4d784ec5" {
		t.Fatalf("wrong digest: %s", hex)
	}

}
<commit_msg>Add example sign in the tests<commit_after>// Copyright 2013 Miek Gieben. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package pkcs11

// These t depend on SoftHSM and the library being in
// in /usr/lib/softhsm/libsofthsm.so

import (
	"fmt"
	"math/big"
	"os"
	"testing"
)

func setenv() *Ctx {
	wd, _ := os.Getwd()
	os.Setenv("SOFTHSM_CONF", wd+"/softhsm.conf")
	p := New("/usr/lib/softhsm/libsofthsm.so")
	// Debug lib
	// p := New("/home/miek/libsofthsm.so")
	return p
}

func getSession(p *Ctx, t *testing.T) SessionHandle {
	if e := p.Initialize(); e != nil {
		t.Fatalf("init error %s\n", e.Error())
	}
	slots, e := p.GetSlotList(true)
	if e != nil {
		t.Fatalf("slots %s\n", e.Error())
	}
	session, e := p.OpenSession(slots[0], CKF_SERIAL_SESSION)
	if e != nil {
		t.Fatalf("session %s\n", e.Error())
	}
	if e := p.Login(session, CKU_USER, "1234"); e != nil {
		t.Fatal("user pin %s\n", e.Error())
	}
	return session
}

func TestGetInfo(t *testing.T) {
	p := setenv()
	session := getSession(p, t)
	defer p.Logout(session)
	defer p.CloseSession(session)
	defer p.Finalize()
	defer p.Destroy()
	info, err := p.GetInfo()
	if err != nil {
		t.Fatalf("Non zero error %s\n", err.Error())
	}
	if info.ManufacturerID != "SoftHSM" {
		t.Fatal("ID should be SoftHSM")
	}
	t.Logf("%+v\n", info)
}

func TestObjectFinding(t *testing.T) {
	p := setenv()
	session := getSession(p, t)
	defer p.Logout(session)
	defer p.CloseSession(session)
	defer p.Finalize()
	defer p.Destroy()
	// There are 2 keys in the db with this tag
	template := []*Attribute{NewAttribute(CKA_LABEL, "MyFirstKey")}
	if e := p.FindObjectsInit(session, template); e != nil {
		t.Fatalf("Failed to init: %s\n", e.Error())
	}
	obj, b, e := p.FindObjects(session, 2)
	if e != nil {
		t.Fatalf("Failed to find: %s %v\n", e.Error(), b)
	}
	if e := p.FindObjectsFinal(session); e != nil {
		t.Fatalf("Failed to finalize: %s\n", e.Error())
	}
	if len(obj) != 2 {
		t.Fatal("should have found two objects")
	}
}

func TestGetAttributeValue(t *testing.T) {
	p := setenv()
	session := getSession(p, t)
	defer p.Logout(session)
	defer p.Destroy()
	defer p.Finalize()
	defer p.CloseSession(session)
	// There are at least two RSA keys in the hsm.db, objecthandle 1 and 2.
	template := []*Attribute{
		NewAttribute(CKA_PUBLIC_EXPONENT, nil),
		NewAttribute(CKA_MODULUS_BITS, nil),
		NewAttribute(CKA_MODULUS, nil),
		NewAttribute(CKA_LABEL, nil),
	}
	// ObjectHandle two is the public key
	attr, err := p.GetAttributeValue(session, ObjectHandle(2), template)
	if err != nil {
		t.Fatalf("err %s\n", err.Error())
	}
	for i, a := range attr {
		t.Logf("Attr %d, type %d, valuelen %d", i, a.Type, len(a.Value))
		if a.Type == CKA_MODULUS {
			mod := big.NewInt(0)
			mod.SetBytes(a.Value)
			t.Logf("Modulus %s\n", mod.String())
		}
	}
}

func TestDigest(t *testing.T) {
	p := setenv()
	session := getSession(p, t)
	defer p.Logout(session)
	defer p.CloseSession(session)
	defer p.Finalize()
	defer p.Destroy()
	e := p.DigestInit(session, []*Mechanism{NewMechanism(CKM_SHA_1, nil)})
	if e != nil {
		t.Fatalf("DigestInit: %s\n", e.Error())
	}

	hash, e := p.Digest(session, []byte("this is a string"))
	if e != nil {
		t.Fatalf("Digest: %s\n", e.Error())
	}
	hex := ""
	for _, d := range hash {
		hex += fmt.Sprintf("%x", d)
	}
	// Teststring create with: echo -n "this is a string" | sha1sum
	if hex != "517592df8fec3ad146a79a9af153db2a4d784ec5" {
		t.Fatalf("wrong digest: %s", hex)
	}
}

func TestDigestUpdate(t *testing.T) {
	p := setenv()
	session := getSession(p, t)
	defer p.Logout(session)
	defer p.CloseSession(session)
	defer p.Finalize()
	defer p.Destroy()
	if e := p.DigestInit(session, []*Mechanism{NewMechanism(CKM_SHA_1, nil)}); e != nil {
		t.Fatalf("DigestInit: %s\n", e.Error())
	}
	if e := p.DigestUpdate(session, []byte("this is ")); e != nil {
		t.Fatalf("DigestUpdate: %s\n", e.Error())
	}
	if e := p.DigestUpdate(session, []byte("a string")); e != nil {
		t.Fatalf("DigestUpdate: %s\n", e.Error())
	}
	hash, e := p.DigestFinal(session)
	if e != nil {
		t.Fatalf("DigestFinal: %s\n", e.Error())
	}
	hex := ""
	for _, d := range hash {
		hex += fmt.Sprintf("%x", d)
	}
	// Teststring create with: echo -n "this is a string" | sha1sum
	if hex != "517592df8fec3ad146a79a9af153db2a4d784ec5" {
		t.Fatalf("wrong digest: %s", hex)
	}

}

// ExampleSign show how to sign some data with a private key.
// Note: error correction is not implemented in this function.
func ExampleSign() {
	p := setenv()
	p.Initialize()
	defer p.Destroy()
	defer p.Finalize()
	slots, _ := p.GetSlotList(true)
	session, _ := p.OpenSession(slots[0], CKF_SERIAL_SESSION|CKF_RW_SESSION)
	defer p.CloseSession(session)
	p.Login(session, CKU_USER, "1234")
	defer p.Logout(session)
	publicKeyTemplate := []*Attribute{
		NewAttribute(CKA_KEY_TYPE, CKO_PUBLIC_KEY),
		NewAttribute(CKA_TOKEN, true),
		NewAttribute(CKA_ENCRYPT, true),
		NewAttribute(CKA_PUBLIC_EXPONENT, []byte{3}),
		NewAttribute(CKA_MODULUS_BITS, 1024),
		NewAttribute(CKA_LABEL, "MyFirstKey"),
	}
	privateKeyTemplate := []*Attribute{
		NewAttribute(CKA_KEY_TYPE, CKO_PRIVATE_KEY),
		NewAttribute(CKA_TOKEN, true),
		NewAttribute(CKA_PRIVATE, true),
		NewAttribute(CKA_SIGN, true),
		NewAttribute(CKA_LABEL, "MyFirstKey"),
	}
	pub, priv, _ := p.GenerateKeyPair(session,
		[]*Mechanism{NewMechanism(CKM_RSA_PKCS_KEY_PAIR_GEN, nil)},
		publicKeyTemplate, privateKeyTemplate)
	p.SignInit(session, []*Mechanism{NewMechanism(CKM_SHA1_RSA_PKCS, nil)}, priv)
	// Sign something with the private key.
	data := []byte("Lets sign this data")

	sig, _ := p.Sign(session, data)
	fmt.Printf("%v validate with %v\n", sig, pub)
}
<|endoftext|>


<commit_before>package log

import (
	crdv1 "github.com/kubernetes-incubator/external-storage/snapshot/pkg/apis/crd/v1"
	"github.com/sirupsen/logrus"
	appv1 "k8s.io/api/apps/v1"
	appv1beta1 "k8s.io/api/apps/v1beta1"
	appv1beta2 "k8s.io/api/apps/v1beta2"
	"k8s.io/api/core/v1"
)

// PodLog Format a log message with pod information
func PodLog(pod *v1.Pod) *logrus.Entry {
	if pod != nil {
		return logrus.WithFields(logrus.Fields{
			"PodName": pod.Name,
		})
	}
	return logrus.WithFields(logrus.Fields{
		"Pod": pod,
	})
}

// DeploymentV1Log Format a log message with deployment information
func DeploymentV1Log(deployment *appv1.Deployment) *logrus.Entry {
	if deployment != nil {
		return logrus.WithFields(logrus.Fields{
			"DeploymentName": deployment.Name,
		})
	}
	return logrus.WithFields(logrus.Fields{
		"Deployment": deployment,
	})
}

// DeploymentV1Beta1Log Format a log message with deployment information
func DeploymentV1Beta1Log(deployment *appv1beta1.Deployment) *logrus.Entry {
	if deployment != nil {
		return logrus.WithFields(logrus.Fields{
			"DeploymentName": deployment.Name,
		})
	}
	return logrus.WithFields(logrus.Fields{
		"Deployment": deployment,
	})
}

// DeploymentV1Beta2Log Format a log message with deployment information
func DeploymentV1Beta2Log(deployment *appv1beta2.Deployment) *logrus.Entry {
	if deployment != nil {
		return logrus.WithFields(logrus.Fields{
			"DeploymentName": deployment.Name,
		})
	}
	return logrus.WithFields(logrus.Fields{
		"Deployment": deployment,
	})
}

// StatefulSetV1Log Format a log message with statefulset information
func StatefulSetV1Log(ss *appv1.StatefulSet) *logrus.Entry {
	if ss != nil {
		return logrus.WithFields(logrus.Fields{
			"StatefulSetName": ss.Name,
		})
	}
	return logrus.WithFields(logrus.Fields{
		"StatefulSet": ss,
	})
}

// StatefulSetV1Beta1Log Format a log message with statefulset information
func StatefulSetV1Beta1Log(ss *appv1beta1.StatefulSet) *logrus.Entry {
	if ss != nil {
		return logrus.WithFields(logrus.Fields{
			"StatefulSetName": ss.Name,
		})
	}
	return logrus.WithFields(logrus.Fields{
		"StatefulSet": ss,
	})
}

// StatefulSetV1Beta2Log Format a log message with statefulset information
func StatefulSetV1Beta2Log(ss *appv1beta2.StatefulSet) *logrus.Entry {
	if ss != nil {
		return logrus.WithFields(logrus.Fields{
			"StatefulSetName": ss.Name,
		})
	}
	return logrus.WithFields(logrus.Fields{
		"StatefulSet": ss,
	})
}

// SnapshotLog formats a log message with snapshot information
func SnapshotLog(snap *crdv1.VolumeSnapshot) *logrus.Entry {
	if snap != nil {
		return logrus.WithFields(logrus.Fields{
			"SnapshotNamespace": snap.Metadata.Namespace,
			"SnapshotName":      snap.Metadata.Name,
		})
	}

	return logrus.WithFields(logrus.Fields{
		"Snapshot": snap,
	})
}
<commit_msg>Add namespace and other info for logs<commit_after>package log

import (
	crdv1 "github.com/kubernetes-incubator/external-storage/snapshot/pkg/apis/crd/v1"
	"github.com/sirupsen/logrus"
	appv1 "k8s.io/api/apps/v1"
	appv1beta1 "k8s.io/api/apps/v1beta1"
	appv1beta2 "k8s.io/api/apps/v1beta2"
	"k8s.io/api/core/v1"
)

// PodLog Format a log message with pod information
func PodLog(pod *v1.Pod) *logrus.Entry {
	if pod != nil {
		fields := logrus.Fields{
			"PodName":   pod.Name,
			"Namespace": pod.Namespace,
		}
		for _, owner := range pod.OwnerReferences {
			if *owner.Controller {
				fields["Owner"] = owner.Kind + "/" + owner.Name
				break
			}
		}
		return logrus.WithFields(fields)
	}
	return logrus.WithFields(logrus.Fields{
		"Pod": pod,
	})
}

// DeploymentV1Log Format a log message with deployment information
func DeploymentV1Log(deployment *appv1.Deployment) *logrus.Entry {
	if deployment != nil {
		return logrus.WithFields(logrus.Fields{
			"DeploymentName": deployment.Name,
			"Namespace":      deployment.Namespace,
		})
	}
	return logrus.WithFields(logrus.Fields{
		"Deployment": deployment,
	})
}

// DeploymentV1Beta1Log Format a log message with deployment information
func DeploymentV1Beta1Log(deployment *appv1beta1.Deployment) *logrus.Entry {
	if deployment != nil {
		return logrus.WithFields(logrus.Fields{
			"DeploymentName": deployment.Name,
			"Namespace":      deployment.Namespace,
		})
	}
	return logrus.WithFields(logrus.Fields{
		"Deployment": deployment,
	})
}

// DeploymentV1Beta2Log Format a log message with deployment information
func DeploymentV1Beta2Log(deployment *appv1beta2.Deployment) *logrus.Entry {
	if deployment != nil {
		return logrus.WithFields(logrus.Fields{
			"DeploymentName": deployment.Name,
			"Namespace":      deployment.Namespace,
		})
	}
	return logrus.WithFields(logrus.Fields{
		"Deployment": deployment,
	})
}

// StatefulSetV1Log Format a log message with statefulset information
func StatefulSetV1Log(ss *appv1.StatefulSet) *logrus.Entry {
	if ss != nil {
		return logrus.WithFields(logrus.Fields{
			"StatefulSetName": ss.Name,
			"Namespace":       ss.Namespace,
		})
	}
	return logrus.WithFields(logrus.Fields{
		"StatefulSet": ss,
	})
}

// StatefulSetV1Beta1Log Format a log message with statefulset information
func StatefulSetV1Beta1Log(ss *appv1beta1.StatefulSet) *logrus.Entry {
	if ss != nil {
		return logrus.WithFields(logrus.Fields{
			"StatefulSetName": ss.Name,
			"Namespace":       ss.Namespace,
		})
	}
	return logrus.WithFields(logrus.Fields{
		"StatefulSet": ss,
	})
}

// StatefulSetV1Beta2Log Format a log message with statefulset information
func StatefulSetV1Beta2Log(ss *appv1beta2.StatefulSet) *logrus.Entry {
	if ss != nil {
		return logrus.WithFields(logrus.Fields{
			"StatefulSetName": ss.Name,
			"Namespace":       ss.Namespace,
		})
	}
	return logrus.WithFields(logrus.Fields{
		"StatefulSet": ss,
	})
}

// SnapshotLog formats a log message with snapshot information
func SnapshotLog(snap *crdv1.VolumeSnapshot) *logrus.Entry {
	if snap != nil {
		return logrus.WithFields(logrus.Fields{
			"SnapshotName": snap.Metadata.Name,
			"Namespace":    snap.Metadata.Namespace,
		})
	}

	return logrus.WithFields(logrus.Fields{
		"Snapshot": snap,
	})
}
<|endoftext|>


<commit_before>// Package power provides a library to read SysFS info on battery state.
package power

import (
	"fmt"
	"io/ioutil"
	"path/filepath"
	"strconv"
	"strings"
)

// Glob for SysFS paths, under which energy_now, energy_full and state files are assumed to exist.
var path = "/sys/class/power_supply/BAT*/"

const (
	Empty State = iota
	Full
	Charging
	Unknown
)

var statees = [...]string{
	"Empty",
	"Full",
	"Charging",
	"Discharging",
	"Unknown",
}

func GetState(s string) (State, error) {
	for i, name := range statees {
		if strings.EqualFold(name, s) {
			return State(i), nil
		}
	}
	return State(0), fmt.Errorf("no state named %v", s)
}

func (s State) String() string {
	return statees[s]
}

type State int

type Battery struct {
	Current float32 // current charge, [0.0, 1.0]
	State   State
}

// String forms a pretty string representation of the battery.
func (b Battery) String() string {
	return fmt.Sprintf("%-12s (%.2f%%)", b.State, 100*b.Current)
}

// readGlob reads the file contents at a glob and returns their contents.
func readGlob(glob string) ([]string, error) {
	paths, err := filepath.Glob(glob)
	if err != nil {
		return []string{}, err
	}
	result := make([]string, len(paths))
	for i, p := range paths {
		bytes, err := ioutil.ReadFile(p)
		if err != nil {
			return []string{}, err
		}
		result[i] = strings.TrimRight(string(bytes), "\n")
	}
	return result, nil
}

// parseCharge parses the charge percentage from string values.
func parseCharge(p, f string) (float32, error) {
	pi, err := strconv.ParseInt(p, 10, 0)
	if err != nil {
		return 0.0, err
	}
	fi, err := strconv.ParseInt(f, 10, 0)
	if err != nil {
		return 0.0, err
	}
	return float32(pi) / float32(fi), nil
}

// Get reads SysFS paths to find state of batteries.
func Get() ([]Battery, error) {
	pwr, err := readGlob(path + "energy_now")
	if err != nil {
		return []Battery{}, fmt.Errorf("couldn't read SysFS %s/energy_now: %v\n", path, err)
	}
	state, err := readGlob(path + "status")
	if err != nil {
		return []Battery{}, fmt.Errorf("couldn't read SysFS %s/status: %v\n", path, err)
	}
	full, err := readGlob(path + "energy_full")
	if err != nil {
		return []Battery{}, fmt.Errorf("couldn't read SysFS %s/energy_full: %v\n", path, err)
	}
	if len(pwr) != len(state) || len(state) != len(full) {
		return []Battery{}, fmt.Errorf("%d power_now files, %d state files but %d energy_full files; expected all to exist\n", len(pwr), len(state), len(full))
	}
	result := make([]Battery, len(pwr))
	for i := range state {
		c, err := parseCharge(pwr[i], full[i])
		if err != nil {
			return []Battery{}, fmt.Errorf("couldn't parse battery charge: %v\n", err)
		}
		state, err := GetState(state[i])
		if err != nil {
			return []Battery{}, err
		}
		result[i] = Battery{
			Current: c,
			State:   state,
		}
	}
	return result, nil
}
<commit_msg>fixes typo<commit_after>// Package power provides a library to read SysFS info on battery state.
package power

import (
	"fmt"
	"io/ioutil"
	"path/filepath"
	"strconv"
	"strings"
)

// Glob for SysFS paths, under which energy_now, energy_full and state files are assumed to exist.
var path = "/sys/class/power_supply/BAT*/"

const (
	Empty State = iota
	Full
	Charging
	Unknown
)

var states = [...]string{
	"Empty",
	"Full",
	"Charging",
	"Discharging",
	"Unknown",
}

func GetState(s string) (State, error) {
	for i, name := range states {
		if strings.EqualFold(name, s) {
			return State(i), nil
		}
	}
	return State(0), fmt.Errorf("no state named %v", s)
}

func (s State) String() string {
	return states[s]
}

type State int

type Battery struct {
	Current float32 // current charge, [0.0, 1.0]
	State   State
}

// String forms a pretty string representation of the battery.
func (b Battery) String() string {
	return fmt.Sprintf("%-12s (%.2f%%)", b.State, 100*b.Current)
}

// readGlob reads the file contents at a glob and returns their contents.
func readGlob(glob string) ([]string, error) {
	paths, err := filepath.Glob(glob)
	if err != nil {
		return []string{}, err
	}
	result := make([]string, len(paths))
	for i, p := range paths {
		bytes, err := ioutil.ReadFile(p)
		if err != nil {
			return []string{}, err
		}
		result[i] = strings.TrimRight(string(bytes), "\n")
	}
	return result, nil
}

// parseCharge parses the charge percentage from string values.
func parseCharge(p, f string) (float32, error) {
	pi, err := strconv.ParseInt(p, 10, 0)
	if err != nil {
		return 0.0, err
	}
	fi, err := strconv.ParseInt(f, 10, 0)
	if err != nil {
		return 0.0, err
	}
	return float32(pi) / float32(fi), nil
}

// Get reads SysFS paths to find state of batteries.
func Get() ([]Battery, error) {
	pwr, err := readGlob(path + "energy_now")
	if err != nil {
		return []Battery{}, fmt.Errorf("couldn't read SysFS %s/energy_now: %v\n", path, err)
	}
	state, err := readGlob(path + "status")
	if err != nil {
		return []Battery{}, fmt.Errorf("couldn't read SysFS %s/status: %v\n", path, err)
	}
	full, err := readGlob(path + "energy_full")
	if err != nil {
		return []Battery{}, fmt.Errorf("couldn't read SysFS %s/energy_full: %v\n", path, err)
	}
	if len(pwr) != len(state) || len(state) != len(full) {
		return []Battery{}, fmt.Errorf("%d power_now files, %d state files but %d energy_full files; expected all to exist\n", len(pwr), len(state), len(full))
	}
	result := make([]Battery, len(pwr))
	for i := range state {
		c, err := parseCharge(pwr[i], full[i])
		if err != nil {
			return []Battery{}, fmt.Errorf("couldn't parse battery charge: %v\n", err)
		}
		state, err := GetState(state[i])
		if err != nil {
			return []Battery{}, err
		}
		result[i] = Battery{
			Current: c,
			State:   state,
		}
	}
	return result, nil
}
<|endoftext|>


<commit_before>// SPDX-License-Identifier: MIT

package mux

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/issue9/assert/v2"
	"github.com/issue9/assert/v2/rest"
)

func (t *tester) prefix(p string) *Prefix {
	return t.router.Prefix(p)
}

func TestPrefix(t *testing.T) {
	test := newTester(t)
	p := test.prefix("/p")

	p.Get("/h/1", rest.BuildHandler(test.a, 201, "", nil))
	test.matchCode(http.MethodGet, "/p/h/1", 201)
	p.GetFunc("/f/1", rest.BuildHandlerFunc(test.a, 201, "", nil))
	test.matchCode(http.MethodGet, "/p/f/1", 201)

	p.Post("/h/1", rest.BuildHandler(test.a, 202, "", nil))
	test.matchCode(http.MethodPost, "/p/h/1", 202)
	p.PostFunc("/f/1", rest.BuildHandlerFunc(test.a, 202, "", nil))
	test.matchCode(http.MethodPost, "/p/f/1", 202)

	p.Put("/h/1", rest.BuildHandler(test.a, 203, "", nil))
	test.matchCode(http.MethodPut, "/p/h/1", 203)
	p.PutFunc("/f/1", rest.BuildHandlerFunc(test.a, 203, "", nil))
	test.matchCode(http.MethodPut, "/p/f/1", 203)

	p.Patch("/h/1", rest.BuildHandler(test.a, 204, "", nil))
	test.matchCode(http.MethodPatch, "/p/h/1", 204)
	p.PatchFunc("/f/1", rest.BuildHandlerFunc(test.a, 204, "", nil))
	test.matchCode(http.MethodPatch, "/p/f/1", 204)

	p.Delete("/h/1", rest.BuildHandler(test.a, 205, "", nil))
	test.matchCode(http.MethodDelete, "/p/h/1", 205)
	p.DeleteFunc("/f/1", rest.BuildHandlerFunc(test.a, 205, "", nil))
	test.matchCode(http.MethodDelete, "/p/f/1", 205)

	// Any
	p.Any("/h/any", rest.BuildHandler(test.a, 206, "", nil))
	test.matchCode(http.MethodGet, "/p/h/any", 206)
	test.matchCode(http.MethodPost, "/p/h/any", 206)
	test.matchCode(http.MethodPut, "/p/h/any", 206)
	test.matchCode(http.MethodPatch, "/p/h/any", 206)
	test.matchCode(http.MethodDelete, "/p/h/any", 206)
	test.matchCode(http.MethodTrace, "/p/h/any", 206)

	p.AnyFunc("/f/any", rest.BuildHandlerFunc(test.a, 206, "", nil))
	test.matchCode(http.MethodGet, "/p/f/any", 206)
	test.matchCode(http.MethodPost, "/p/f/any", 206)
	test.matchCode(http.MethodPut, "/p/f/any", 206)
	test.matchCode(http.MethodPatch, "/p/f/any", 206)
	test.matchCode(http.MethodDelete, "/p/f/any", 206)
	test.matchCode(http.MethodTrace, "/p/f/any", 206)

	// remove
	p.Remove("/f/any", http.MethodDelete, http.MethodGet)
	test.matchCode(http.MethodGet, "/p/f/any", 405)   // 已经删除
	test.matchCode(http.MethodTrace, "/p/f/any", 206) // 未删除

	// clean
	p.Clean()
	test.matchCode(http.MethodTrace, "/p/f/any", 404)
	test.matchOptions("/p/h/1", 404, "")
	test.matchCode(http.MethodDelete, "/p/f/1", 404)
}

func TestRouter_Prefix(t *testing.T) {
	a := assert.New(t, false)
	def := NewRouter("", AllowedCORS)
	a.NotNil(def)

	p := def.Prefix("/abc")
	a.Equal(p.prefix, "/abc")
	a.Equal(p.Router(), def)
	p = def.Prefix("")
	a.Equal(p.prefix, "")

	p = def.Prefix("/abc")
	a.Equal(p.prefix, "/abc")
	a.Equal(p.Router(), def)
	pp := p.Prefix("")
	a.Equal(pp.prefix, "/abc")
	pp.Delete("", rest.BuildHandler(a, 201, "", nil))
	w := httptest.NewRecorder()
	r, err := http.NewRequest(http.MethodDelete, "/abc", nil)
	a.NotError(err).NotNil(r)
	def.ServeHTTP(w, r)
	a.Equal(w.Result().StatusCode, 201)
}

func TestPrefix_Prefix(t *testing.T) {
	a := assert.New(t, false)
	def := NewRouter("", AllowedCORS)
	a.NotNil(def)

	p := def.Prefix("/abc", buildMiddleware(a, "p1"), buildMiddleware(a, "p2"))
	pp := p.Prefix("/def", buildMiddleware(a, "pp1"), buildMiddleware(a, "pp2"))
	a.Equal(pp.prefix, "/abc/def")
	a.Equal(p.Router(), def)
	pp.Delete("", rest.BuildHandler(a, 201, "-201-", nil))

	w := httptest.NewRecorder()
	r, err := http.NewRequest(http.MethodDelete, "/abc/def", nil)
	a.NotError(err).NotNil(r)
	def.ServeHTTP(w, r)
	a.Equal(w.Result().StatusCode, 201).
		Equal(w.Body.String(), "-201-p1p2pp1pp2")

	p = def.Prefix("")
	pp = p.Prefix("/abc")
	a.Equal(pp.prefix, "/abc")
}

func TestPrefix_URL(t *testing.T) {
	a := assert.New(t, false)
	def := NewRouter("", AllowedCORS, URLDomain("https://example.com"))
	a.NotNil(def)

	// 非正则
	p := def.Prefix("/api")
	a.NotNil(p)
	url, err := p.URL(false, "/v1", map[string]string{"id": "1"})
	a.NotError(err).Equal(url, "https://example.com/api/v1")

	p = def.Prefix("//api")
	a.NotNil(p)
	url, err = p.URL(false, "/v1", map[string]string{"id": "1"})
	a.NotError(err).Equal(url, "https://example.com//api/v1")

	// 正常的单个参数
	p = def.Prefix("/api")
	a.NotNil(p)
	url, err = p.URL(false, "/{id:\\d+}/{path}", map[string]string{"id": "1", "path": "p1"})
	a.NotError(err).Equal(url, "https://example.com/api/1/p1")

	url, err = p.URL(false, "/{id:\\d+}///{path}", map[string]string{"id": "1", "path": "p1"})
	a.NotError(err).Equal(url, "https://example.com/api/1///p1")

	// 多个参数
	p = def.Prefix("/api")
	a.NotNil(p)
	url, err = p.URL(false, "/{action}/{id:\\d+}", map[string]string{"id": "1", "action": "blog"})
	a.NotError(err).Equal(url, "https://example.com/api/blog/1")

	// 缺少参数
	url, err = p.URL(false, "/{action}/{id:\\d+}", map[string]string{"id": "1"})
	a.Error(err).Equal(url, "")

	url, err = p.URL(false, "/{action}/{id:\\d+}", map[string]string{"id": "1", "action": "blog"})
	a.NotError(err).Equal(url, "https://example.com/api/blog/1")
}
<commit_msg>test: 添加部分测试用例<commit_after>// SPDX-License-Identifier: MIT

package mux

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/issue9/assert/v2"
	"github.com/issue9/assert/v2/rest"
)

func (t *tester) prefix(p string) *Prefix {
	return t.router.Prefix(p)
}

func TestPrefix(t *testing.T) {
	test := newTester(t)
	p := test.prefix("/p")

	p.Get("/h/1", rest.BuildHandler(test.a, 201, "", nil))
	test.matchCode(http.MethodGet, "/p/h/1", 201)
	p.GetFunc("/f/1", rest.BuildHandlerFunc(test.a, 201, "", nil))
	test.matchCode(http.MethodGet, "/p/f/1", 201)

	p.Post("/h/1", rest.BuildHandler(test.a, 202, "", nil))
	test.matchCode(http.MethodPost, "/p/h/1", 202)
	p.PostFunc("/f/1", rest.BuildHandlerFunc(test.a, 202, "", nil))
	test.matchCode(http.MethodPost, "/p/f/1", 202)

	p.Put("/h/1", rest.BuildHandler(test.a, 203, "", nil))
	test.matchCode(http.MethodPut, "/p/h/1", 203)
	p.PutFunc("/f/1", rest.BuildHandlerFunc(test.a, 203, "", nil))
	test.matchCode(http.MethodPut, "/p/f/1", 203)

	p.Patch("/h/1", rest.BuildHandler(test.a, 204, "", nil))
	test.matchCode(http.MethodPatch, "/p/h/1", 204)
	p.PatchFunc("/f/1", rest.BuildHandlerFunc(test.a, 204, "", nil))
	test.matchCode(http.MethodPatch, "/p/f/1", 204)

	p.Delete("/h/1", rest.BuildHandler(test.a, 205, "", nil))
	test.matchCode(http.MethodDelete, "/p/h/1", 205)
	p.DeleteFunc("/f/1", rest.BuildHandlerFunc(test.a, 205, "", nil))
	test.matchCode(http.MethodDelete, "/p/f/1", 205)

	// Any
	p.Any("/h/any", rest.BuildHandler(test.a, 206, "", nil))
	test.matchCode(http.MethodGet, "/p/h/any", 206)
	test.matchCode(http.MethodPost, "/p/h/any", 206)
	test.matchCode(http.MethodPut, "/p/h/any", 206)
	test.matchCode(http.MethodPatch, "/p/h/any", 206)
	test.matchCode(http.MethodDelete, "/p/h/any", 206)
	test.matchCode(http.MethodTrace, "/p/h/any", 206)

	p.AnyFunc("/f/any", rest.BuildHandlerFunc(test.a, 206, "", nil))
	test.matchCode(http.MethodGet, "/p/f/any", 206)
	test.matchCode(http.MethodPost, "/p/f/any", 206)
	test.matchCode(http.MethodPut, "/p/f/any", 206)
	test.matchCode(http.MethodPatch, "/p/f/any", 206)
	test.matchCode(http.MethodDelete, "/p/f/any", 206)
	test.matchCode(http.MethodTrace, "/p/f/any", 206)

	// remove
	p.Remove("/f/any", http.MethodDelete, http.MethodGet)
	test.matchCode(http.MethodGet, "/p/f/any", 405)   // 已经删除
	test.matchCode(http.MethodTrace, "/p/f/any", 206) // 未删除

	// clean
	p.Clean()
	test.matchCode(http.MethodTrace, "/p/f/any", 404)
	test.matchOptions("/p/h/1", 404, "")
	test.matchCode(http.MethodDelete, "/p/f/1", 404)
}

func TestRouter_Prefix(t *testing.T) {
	a := assert.New(t, false)

	a.Run("prefix", func(a *assert.Assertion) {
		def := NewRouter("", AllowedCORS)
		a.NotNil(def)

		p := def.Prefix("/abc")
		a.Equal(p.prefix, "/abc")
		a.Equal(p.Router(), def)

		p = def.Prefix("")
		a.Equal(p.prefix, "")
	}).Run("prefix with middleware", func(a *assert.Assertion) {
		def := NewRouter("", AllowedCORS)
		a.NotNil(def)

		p := def.Prefix("/abc")
		a.Equal(p.prefix, "/abc")
		a.Equal(p.Router(), def)

		pp := p.Prefix("")
		a.Equal(pp.prefix, "/abc")
		pp.Delete("", rest.BuildHandler(a, 201, "", nil))
		w := httptest.NewRecorder()
		r, err := http.NewRequest(http.MethodDelete, "/abc", nil)
		a.NotError(err).NotNil(r)
		def.ServeHTTP(w, r)
		a.Equal(w.Result().StatusCode, 201)
	}).Run("empty prefix with middleware", func(a *assert.Assertion) {
		def := NewRouter("", AllowedCORS)
		a.NotNil(def)

		p := def.Prefix("/abc")
		a.Equal(p.prefix, "/abc")
		a.Equal(p.Router(), def)

		pp := p.Prefix("", buildMiddleware(a, "p1"), buildMiddleware(a, "p2"))
		pp.Delete("", rest.BuildHandler(a, 201, "-201-", nil))
		w := httptest.NewRecorder()
		r, err := http.NewRequest(http.MethodDelete, "/abc", nil)
		a.NotError(err).NotNil(r)
		def.ServeHTTP(w, r)
		a.Equal(w.Result().StatusCode, 201).
			Equal(w.Body.String(), "-201-p1p2")
	})
}

func TestPrefix_Prefix(t *testing.T) {
	a := assert.New(t, false)
	def := NewRouter("", AllowedCORS)
	a.NotNil(def)

	p := def.Prefix("/abc", buildMiddleware(a, "p1"), buildMiddleware(a, "p2"))
	pp := p.Prefix("/def", buildMiddleware(a, "pp1"), buildMiddleware(a, "pp2"))
	a.Equal(pp.prefix, "/abc/def")
	a.Equal(p.Router(), def)
	pp.Delete("", rest.BuildHandler(a, 201, "-201-", nil))

	w := httptest.NewRecorder()
	r, err := http.NewRequest(http.MethodDelete, "/abc/def", nil)
	a.NotError(err).NotNil(r)
	def.ServeHTTP(w, r)
	a.Equal(w.Result().StatusCode, 201).
		Equal(w.Body.String(), "-201-p1p2pp1pp2")

	p = def.Prefix("")
	pp = p.Prefix("/abc")
	a.Equal(pp.prefix, "/abc")
}

func TestPrefix_URL(t *testing.T) {
	a := assert.New(t, false)
	def := NewRouter("", AllowedCORS, URLDomain("https://example.com"))
	a.NotNil(def)

	// 非正则
	p := def.Prefix("/api")
	a.NotNil(p)
	url, err := p.URL(false, "/v1", map[string]string{"id": "1"})
	a.NotError(err).Equal(url, "https://example.com/api/v1")

	p = def.Prefix("//api")
	a.NotNil(p)
	url, err = p.URL(false, "/v1", map[string]string{"id": "1"})
	a.NotError(err).Equal(url, "https://example.com//api/v1")

	// 正常的单个参数
	p = def.Prefix("/api")
	a.NotNil(p)
	url, err = p.URL(false, "/{id:\\d+}/{path}", map[string]string{"id": "1", "path": "p1"})
	a.NotError(err).Equal(url, "https://example.com/api/1/p1")

	url, err = p.URL(false, "/{id:\\d+}///{path}", map[string]string{"id": "1", "path": "p1"})
	a.NotError(err).Equal(url, "https://example.com/api/1///p1")

	// 多个参数
	p = def.Prefix("/api")
	a.NotNil(p)
	url, err = p.URL(false, "/{action}/{id:\\d+}", map[string]string{"id": "1", "action": "blog"})
	a.NotError(err).Equal(url, "https://example.com/api/blog/1")

	// 缺少参数
	url, err = p.URL(false, "/{action}/{id:\\d+}", map[string]string{"id": "1"})
	a.Error(err).Equal(url, "")

	url, err = p.URL(false, "/{action}/{id:\\d+}", map[string]string{"id": "1", "action": "blog"})
	a.NotError(err).Equal(url, "https://example.com/api/blog/1")
}
<|endoftext|>