<commit_before>// ----------------------------------------------------------------------------
//
//     This file is copied here by Magic Modules. The code for building up a
//     sql database instance object is copied from the manually implemented
//     provider file:
//     third_party/terraform/resources/resource_sql_database_instance.go.erb.go
//
// ----------------------------------------------------------------------------
package google

import (
	"regexp"

	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

	sqladmin "google.golang.org/api/sqladmin/v1beta4"
)

func GetSQLDatabaseInstanceCaiObject(d TerraformResourceData, config *Config) ([]Asset, error) {
	name, err := assetName(d, config, "//cloudsql.googleapis.com/projects/{{project}}/instances/{{name}}")
	if err != nil {
		return []Asset{}, err
	}
	if obj, err := GetSQLDatabaseInstanceApiObject(d, config); err == nil {
		return []Asset{{
			Name: name,
			Type: "sqladmin.googleapis.com/Instance",
			Resource: &AssetResource{
				Version:              "v1beta4",
				DiscoveryDocumentURI: "https://www.googleapis.com/discovery/v1/apis/sqladmin/v1beta4/rest",
				DiscoveryName:        "DatabaseInstance",
				Data:                 obj,
			},
		}}, nil
	} else {
		return []Asset{}, err
	}
}

func GetSQLDatabaseInstanceApiObject(d TerraformResourceData, config *Config) (map[string]interface{}, error) {
	project, err := getProject(d, config)
	if err != nil {
		return nil, err
	}

	region, err := getRegion(d, config)
	if err != nil {
		return nil, err
	}

	var name string
	if v, ok := d.GetOk("name"); ok {
		name = v.(string)
	} else {
		name = resource.UniqueId()
	}

	instance := &sqladmin.DatabaseInstance{
		Project:              project,
		Name:                 name,
		Region:               region,
		Settings:             expandSqlDatabaseInstanceSettings(d.Get("settings").([]interface{}), !isFirstGen(d)),
		DatabaseVersion:      d.Get("database_version").(string),
		MasterInstanceName:   d.Get("master_instance_name").(string),
		ReplicaConfiguration: expandReplicaConfiguration(d.Get("replica_configuration").([]interface{})),
	}

	return jsonMap(instance)
}

// Detects whether a database is 1st Generation by inspecting the tier name
func isFirstGen(d TerraformResourceData) bool {
	settingsList := d.Get("settings").([]interface{})
	settings := settingsList[0].(map[string]interface{})
	tier := settings["tier"].(string)

	// 1st Generation databases have tiers like 'D0', as opposed to 2nd Generation which are
	// prefixed with 'db'
	return !regexp.MustCompile("db*").Match([]byte(tier))
}

func expandSqlDatabaseInstanceSettings(configured []interface{}, secondGen bool) *sqladmin.Settings {
	if len(configured) == 0 || configured[0] == nil {
		return nil
	}

	_settings := configured[0].(map[string]interface{})
	settings := &sqladmin.Settings{
		// Version is unset in Create but is set during update
		SettingsVersion:             int64(_settings["version"].(int)),
		Tier:                        _settings["tier"].(string),
		ForceSendFields:             []string{"StorageAutoResize"},
		ActivationPolicy:            _settings["activation_policy"].(string),
		AvailabilityType:            _settings["availability_type"].(string),
		CrashSafeReplicationEnabled: _settings["crash_safe_replication"].(bool),
		DataDiskSizeGb:              int64(_settings["disk_size"].(int)),
		DataDiskType:                _settings["disk_type"].(string),
		PricingPlan:                 _settings["pricing_plan"].(string),
		ReplicationType:             _settings["replication_type"].(string),
		UserLabels:                  convertStringMap(_settings["user_labels"].(map[string]interface{})),
		BackupConfiguration:         expandBackupConfiguration(_settings["backup_configuration"].([]interface{})),
		DatabaseFlags:               expandDatabaseFlags(_settings["database_flags"].([]interface{})),
		AuthorizedGaeApplications:   expandAuthorizedGaeApplications(_settings["authorized_gae_applications"].([]interface{})),
		IpConfiguration:             expandIpConfiguration(_settings["ip_configuration"].([]interface{})),
		LocationPreference:          expandLocationPreference(_settings["location_preference"].([]interface{})),
		MaintenanceWindow:           expandMaintenanceWindow(_settings["maintenance_window"].([]interface{})),
	}

	// 1st Generation instances don't support the disk_autoresize parameter
	// and it defaults to true - so we shouldn't set it if this is first gen
	if secondGen {
		diskAutoresize := _settings["disk_autoresize"].(bool)
		settings.StorageAutoResize = &diskAutoresize
	}

	return settings
}

func expandReplicaConfiguration(configured []interface{}) *sqladmin.ReplicaConfiguration {
	if len(configured) == 0 || configured[0] == nil {
		return nil
	}

	_replicaConfiguration := configured[0].(map[string]interface{})
	return &sqladmin.ReplicaConfiguration{
		FailoverTarget: _replicaConfiguration["failover_target"].(bool),

		// MysqlReplicaConfiguration has been flattened in the TF schema, so
		// we'll keep it flat here instead of another expand method.
		MysqlReplicaConfiguration: &sqladmin.MySqlReplicaConfiguration{
			CaCertificate:           _replicaConfiguration["ca_certificate"].(string),
			ClientCertificate:       _replicaConfiguration["client_certificate"].(string),
			ClientKey:               _replicaConfiguration["client_key"].(string),
			ConnectRetryInterval:    int64(_replicaConfiguration["connect_retry_interval"].(int)),
			DumpFilePath:            _replicaConfiguration["dump_file_path"].(string),
			MasterHeartbeatPeriod:   int64(_replicaConfiguration["master_heartbeat_period"].(int)),
			Password:                _replicaConfiguration["password"].(string),
			SslCipher:               _replicaConfiguration["ssl_cipher"].(string),
			Username:                _replicaConfiguration["username"].(string),
			VerifyServerCertificate: _replicaConfiguration["verify_server_certificate"].(bool),
		},
	}
}

func expandMaintenanceWindow(configured []interface{}) *sqladmin.MaintenanceWindow {
	if len(configured) == 0 || configured[0] == nil {
		return nil
	}

	window := configured[0].(map[string]interface{})
	return &sqladmin.MaintenanceWindow{
		Day:             int64(window["day"].(int)),
		Hour:            int64(window["hour"].(int)),
		UpdateTrack:     window["update_track"].(string),
		ForceSendFields: []string{"Hour"},
	}
}

func expandLocationPreference(configured []interface{}) *sqladmin.LocationPreference {
	if len(configured) == 0 || configured[0] == nil {
		return nil
	}

	_locationPreference := configured[0].(map[string]interface{})
	return &sqladmin.LocationPreference{
		FollowGaeApplication: _locationPreference["follow_gae_application"].(string),
		Zone:                 _locationPreference["zone"].(string),
	}
}

func expandIpConfiguration(configured []interface{}) *sqladmin.IpConfiguration {
	if len(configured) == 0 || configured[0] == nil {
		return nil
	}

	_ipConfiguration := configured[0].(map[string]interface{})

	return &sqladmin.IpConfiguration{
		Ipv4Enabled:        _ipConfiguration["ipv4_enabled"].(bool),
		RequireSsl:         _ipConfiguration["require_ssl"].(bool),
		PrivateNetwork:     _ipConfiguration["private_network"].(string),
		AuthorizedNetworks: expandAuthorizedNetworks(_ipConfiguration["authorized_networks"].(*schema.Set).List()),
		ForceSendFields:    []string{"Ipv4Enabled", "RequireSsl"},
	}
}
func expandAuthorizedNetworks(configured []interface{}) []*sqladmin.AclEntry {
	an := make([]*sqladmin.AclEntry, 0, len(configured))
	for _, _acl := range configured {
		_entry := _acl.(map[string]interface{})
		an = append(an, &sqladmin.AclEntry{
			ExpirationTime: _entry["expiration_time"].(string),
			Name:           _entry["name"].(string),
			Value:          _entry["value"].(string),
		})
	}

	return an
}

func expandAuthorizedGaeApplications(configured []interface{}) []string {
	aga := make([]string, 0, len(configured))
	for _, app := range configured {
		aga = append(aga, app.(string))
	}
	return aga
}

func expandDatabaseFlags(configured []interface{}) []*sqladmin.DatabaseFlags {
	databaseFlags := make([]*sqladmin.DatabaseFlags, 0, len(configured))
	for _, _flag := range configured {
		_entry := _flag.(map[string]interface{})

		databaseFlags = append(databaseFlags, &sqladmin.DatabaseFlags{
			Name:  _entry["name"].(string),
			Value: _entry["value"].(string),
		})
	}
	return databaseFlags
}

func expandBackupConfiguration(configured []interface{}) *sqladmin.BackupConfiguration {
	if len(configured) == 0 || configured[0] == nil {
		return nil
	}

	_backupConfiguration := configured[0].(map[string]interface{})
	return &sqladmin.BackupConfiguration{
		BinaryLogEnabled: _backupConfiguration["binary_log_enabled"].(bool),
		Enabled:          _backupConfiguration["enabled"].(bool),
		StartTime:        _backupConfiguration["start_time"].(string),
		Location:         _backupConfiguration["location"].(string),
	}
}
<commit_msg>Add option to set autoresize limit (#4743) (#709)<commit_after>// ----------------------------------------------------------------------------
//
//     This file is copied here by Magic Modules. The code for building up a
//     sql database instance object is copied from the manually implemented
//     provider file:
//     third_party/terraform/resources/resource_sql_database_instance.go.erb.go
//
// ----------------------------------------------------------------------------
package google

import (
	"regexp"

	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

	sqladmin "google.golang.org/api/sqladmin/v1beta4"
)

func GetSQLDatabaseInstanceCaiObject(d TerraformResourceData, config *Config) ([]Asset, error) {
	name, err := assetName(d, config, "//cloudsql.googleapis.com/projects/{{project}}/instances/{{name}}")
	if err != nil {
		return []Asset{}, err
	}
	if obj, err := GetSQLDatabaseInstanceApiObject(d, config); err == nil {
		return []Asset{{
			Name: name,
			Type: "sqladmin.googleapis.com/Instance",
			Resource: &AssetResource{
				Version:              "v1beta4",
				DiscoveryDocumentURI: "https://www.googleapis.com/discovery/v1/apis/sqladmin/v1beta4/rest",
				DiscoveryName:        "DatabaseInstance",
				Data:                 obj,
			},
		}}, nil
	} else {
		return []Asset{}, err
	}
}

func GetSQLDatabaseInstanceApiObject(d TerraformResourceData, config *Config) (map[string]interface{}, error) {
	project, err := getProject(d, config)
	if err != nil {
		return nil, err
	}

	region, err := getRegion(d, config)
	if err != nil {
		return nil, err
	}

	var name string
	if v, ok := d.GetOk("name"); ok {
		name = v.(string)
	} else {
		name = resource.UniqueId()
	}

	instance := &sqladmin.DatabaseInstance{
		Project:              project,
		Name:                 name,
		Region:               region,
		Settings:             expandSqlDatabaseInstanceSettings(d.Get("settings").([]interface{}), !isFirstGen(d)),
		DatabaseVersion:      d.Get("database_version").(string),
		MasterInstanceName:   d.Get("master_instance_name").(string),
		ReplicaConfiguration: expandReplicaConfiguration(d.Get("replica_configuration").([]interface{})),
	}

	return jsonMap(instance)
}

// Detects whether a database is 1st Generation by inspecting the tier name
func isFirstGen(d TerraformResourceData) bool {
	settingsList := d.Get("settings").([]interface{})
	settings := settingsList[0].(map[string]interface{})
	tier := settings["tier"].(string)

	// 1st Generation databases have tiers like 'D0', as opposed to 2nd Generation which are
	// prefixed with 'db'
	return !regexp.MustCompile("db*").Match([]byte(tier))
}

func expandSqlDatabaseInstanceSettings(configured []interface{}, secondGen bool) *sqladmin.Settings {
	if len(configured) == 0 || configured[0] == nil {
		return nil
	}

	_settings := configured[0].(map[string]interface{})
	settings := &sqladmin.Settings{
		// Version is unset in Create but is set during update
		SettingsVersion:             int64(_settings["version"].(int)),
		Tier:                        _settings["tier"].(string),
		ForceSendFields:             []string{"StorageAutoResize"},
		ActivationPolicy:            _settings["activation_policy"].(string),
		AvailabilityType:            _settings["availability_type"].(string),
		CrashSafeReplicationEnabled: _settings["crash_safe_replication"].(bool),
		DataDiskSizeGb:              int64(_settings["disk_size"].(int)),
		DataDiskType:                _settings["disk_type"].(string),
		PricingPlan:                 _settings["pricing_plan"].(string),
		ReplicationType:             _settings["replication_type"].(string),
		UserLabels:                  convertStringMap(_settings["user_labels"].(map[string]interface{})),
		BackupConfiguration:         expandBackupConfiguration(_settings["backup_configuration"].([]interface{})),
		DatabaseFlags:               expandDatabaseFlags(_settings["database_flags"].([]interface{})),
		AuthorizedGaeApplications:   expandAuthorizedGaeApplications(_settings["authorized_gae_applications"].([]interface{})),
		IpConfiguration:             expandIpConfiguration(_settings["ip_configuration"].([]interface{})),
		LocationPreference:          expandLocationPreference(_settings["location_preference"].([]interface{})),
		MaintenanceWindow:           expandMaintenanceWindow(_settings["maintenance_window"].([]interface{})),
	}

	// 1st Generation instances don't support the disk_autoresize parameter
	// and it defaults to true - so we shouldn't set it if this is first gen
	if secondGen {
		diskAutoresize := _settings["disk_autoresize"].(bool)
		settings.StorageAutoResize = &diskAutoresize
		settings.StorageAutoResizeLimit = int64(_settings["disk_autoresize_limit"].(int))
	}

	return settings
}

func expandReplicaConfiguration(configured []interface{}) *sqladmin.ReplicaConfiguration {
	if len(configured) == 0 || configured[0] == nil {
		return nil
	}

	_replicaConfiguration := configured[0].(map[string]interface{})
	return &sqladmin.ReplicaConfiguration{
		FailoverTarget: _replicaConfiguration["failover_target"].(bool),

		// MysqlReplicaConfiguration has been flattened in the TF schema, so
		// we'll keep it flat here instead of another expand method.
		MysqlReplicaConfiguration: &sqladmin.MySqlReplicaConfiguration{
			CaCertificate:           _replicaConfiguration["ca_certificate"].(string),
			ClientCertificate:       _replicaConfiguration["client_certificate"].(string),
			ClientKey:               _replicaConfiguration["client_key"].(string),
			ConnectRetryInterval:    int64(_replicaConfiguration["connect_retry_interval"].(int)),
			DumpFilePath:            _replicaConfiguration["dump_file_path"].(string),
			MasterHeartbeatPeriod:   int64(_replicaConfiguration["master_heartbeat_period"].(int)),
			Password:                _replicaConfiguration["password"].(string),
			SslCipher:               _replicaConfiguration["ssl_cipher"].(string),
			Username:                _replicaConfiguration["username"].(string),
			VerifyServerCertificate: _replicaConfiguration["verify_server_certificate"].(bool),
		},
	}
}

func expandMaintenanceWindow(configured []interface{}) *sqladmin.MaintenanceWindow {
	if len(configured) == 0 || configured[0] == nil {
		return nil
	}

	window := configured[0].(map[string]interface{})
	return &sqladmin.MaintenanceWindow{
		Day:             int64(window["day"].(int)),
		Hour:            int64(window["hour"].(int)),
		UpdateTrack:     window["update_track"].(string),
		ForceSendFields: []string{"Hour"},
	}
}

func expandLocationPreference(configured []interface{}) *sqladmin.LocationPreference {
	if len(configured) == 0 || configured[0] == nil {
		return nil
	}

	_locationPreference := configured[0].(map[string]interface{})
	return &sqladmin.LocationPreference{
		FollowGaeApplication: _locationPreference["follow_gae_application"].(string),
		Zone:                 _locationPreference["zone"].(string),
	}
}

func expandIpConfiguration(configured []interface{}) *sqladmin.IpConfiguration {
	if len(configured) == 0 || configured[0] == nil {
		return nil
	}

	_ipConfiguration := configured[0].(map[string]interface{})

	return &sqladmin.IpConfiguration{
		Ipv4Enabled:        _ipConfiguration["ipv4_enabled"].(bool),
		RequireSsl:         _ipConfiguration["require_ssl"].(bool),
		PrivateNetwork:     _ipConfiguration["private_network"].(string),
		AuthorizedNetworks: expandAuthorizedNetworks(_ipConfiguration["authorized_networks"].(*schema.Set).List()),
		ForceSendFields:    []string{"Ipv4Enabled", "RequireSsl"},
	}
}
func expandAuthorizedNetworks(configured []interface{}) []*sqladmin.AclEntry {
	an := make([]*sqladmin.AclEntry, 0, len(configured))
	for _, _acl := range configured {
		_entry := _acl.(map[string]interface{})
		an = append(an, &sqladmin.AclEntry{
			ExpirationTime: _entry["expiration_time"].(string),
			Name:           _entry["name"].(string),
			Value:          _entry["value"].(string),
		})
	}

	return an
}

func expandAuthorizedGaeApplications(configured []interface{}) []string {
	aga := make([]string, 0, len(configured))
	for _, app := range configured {
		aga = append(aga, app.(string))
	}
	return aga
}

func expandDatabaseFlags(configured []interface{}) []*sqladmin.DatabaseFlags {
	databaseFlags := make([]*sqladmin.DatabaseFlags, 0, len(configured))
	for _, _flag := range configured {
		_entry := _flag.(map[string]interface{})

		databaseFlags = append(databaseFlags, &sqladmin.DatabaseFlags{
			Name:  _entry["name"].(string),
			Value: _entry["value"].(string),
		})
	}
	return databaseFlags
}

func expandBackupConfiguration(configured []interface{}) *sqladmin.BackupConfiguration {
	if len(configured) == 0 || configured[0] == nil {
		return nil
	}

	_backupConfiguration := configured[0].(map[string]interface{})
	return &sqladmin.BackupConfiguration{
		BinaryLogEnabled: _backupConfiguration["binary_log_enabled"].(bool),
		Enabled:          _backupConfiguration["enabled"].(bool),
		StartTime:        _backupConfiguration["start_time"].(string),
		Location:         _backupConfiguration["location"].(string),
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
// Licensed under the same terms as Go itself:
// https://code.google.com/p/go/source/browse/LICENSE

package http2

// frameWriteMsg is a request to write a frame.
type frameWriteMsg struct {
	// write is the function that does the writing, once the
	// writeScheduler (below) has decided to select this frame
	// to write. The write functions are all defined in write.go.
	write func(ctx writeContext, v interface{}) error

	// v is the argument passed to the write function. See each
	// function in write.go to see which type they should be,
	// depending on what write is.
	v interface{}

	cost      uint32  // if DATA, number of flow control bytes required
	stream    *stream // used for prioritization
	endStream bool    // stream is being closed locally

	// done, if non-nil, must be a buffered channel with space for
	// 1 message and is sent the return value from write (or an
	// earlier error) when the frame has been written.
	done chan error
}

// writeScheduler tracks pending frames to write, priorities, and decides
// the next one to use. It is not thread-safe.
type writeScheduler struct {
	slice []frameWriteMsg
}

func (ws *writeScheduler) empty() bool { return len(ws.slice) == 0 }

func (ws *writeScheduler) add(wm frameWriteMsg) {
	ws.slice = append(ws.slice, wm)
}

// take returns
func (ws *writeScheduler) take() frameWriteMsg {
	if ws.empty() {
		panic("internal error: writeScheduler.take called when empty")
	}
	// TODO:
	// -- prioritize all non-DATA frames first. they're not flow controlled anyway and
	//    they're generally more important.
	// -- for all DATA frames that are enqueued (and we should enqueue []byte instead of FRAMES),
	//    go over each (in priority order, as determined by the whole priority tree chaos),
	//    and decide which we have tokens for, and how many tokens.

	// Writing on stream X requires that we have tokens on the
	// stream 0 (the conn-as-a-whole stream) as well as stream X.

	// So: find the highest priority stream X, then see: do we
	// have tokens for X? Let's say we have N_X tokens. Then we should
	// write MIN(N_X, TOKENS(conn-wide-tokens)).
	//
	// Any tokens left over? Repeat. Well, not really... the
	// repeat will happen via the next call to
	// scheduleFrameWrite. So keep a HEAP (priqueue) of which
	// streams to write to.

	// TODO: proper scheduler
	wm := ws.slice[0]
	// shift it all down. kinda lame. will be removed later anyway.
	copy(ws.slice, ws.slice[1:])
	ws.slice[len(ws.slice)-1] = frameWriteMsg{}
	ws.slice = ws.slice[:len(ws.slice)-1]
	return wm
}
<commit_msg>Start of a better frame scheduler. Still many TODOs.<commit_after>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
// Licensed under the same terms as Go itself:
// https://code.google.com/p/go/source/browse/LICENSE

package http2

// frameWriteMsg is a request to write a frame.
type frameWriteMsg struct {
	// write is the function that does the writing, once the
	// writeScheduler (below) has decided to select this frame
	// to write. The write functions are all defined in write.go.
	write func(ctx writeContext, v interface{}) error

	// v is the argument passed to the write function. See each
	// function in write.go to see which type they should be,
	// depending on what write is.
	v interface{}

	cost      uint32  // if DATA, number of flow control bytes required
	stream    *stream // used for prioritization
	endStream bool    // stream is being closed locally

	// done, if non-nil, must be a buffered channel with space for
	// 1 message and is sent the return value from write (or an
	// earlier error) when the frame has been written.
	done chan error
}

// writeScheduler tracks pending frames to write, priorities, and decides
// the next one to use. It is not thread-safe.
type writeScheduler struct {
	// zero are frames not associated with a specific stream.
	// They're sent before any stream-specific freams.
	zero writeQueue

	sq map[uint32]*writeQueue
}

func (ws *writeScheduler) empty() bool { return ws.zero.empty() && len(ws.sq) == 0 }

func (ws *writeScheduler) add(wm frameWriteMsg) {
	st := wm.stream
	if st == nil {
		ws.zero.push(wm)
	} else {
		ws.streamQueue(st.id).push(wm)
	}
}

func (ws *writeScheduler) streamQueue(streamID uint32) *writeQueue {
	if q, ok := ws.sq[streamID]; ok {
		return q
	}
	if ws.sq == nil {
		ws.sq = make(map[uint32]*writeQueue)
	}
	q := new(writeQueue)
	ws.sq[streamID] = q
	return q
}

// take returns the most important frame to write and removes it from the scheduler.
// It is illegal to call this if the scheduler is empty.
func (ws *writeScheduler) take() frameWriteMsg {
	// If there any frames not associated with streams, prefer those first.
	// These are usually SETTINGS, etc.
	if !ws.zero.empty() {
		return ws.zero.shift()
	}

	if len(ws.sq) == 0 {
		panic("internal error: take should only be called if non-empty")
	}

	// Next, prioritize frames on streams that aren't DATA frames (no cost).
	for id, q := range ws.sq {
		if q.firstIsNoCost() {
			return ws.takeFrom(id, q)
		}
	}

	// Now, all that remains are DATA frames. So pick the best one.
	// TODO: do that. For now, pick a random one.
	for id, q := range ws.sq {
		return ws.takeFrom(id, q)
	}
	panic("internal error: take should only be called if non-empty")
}

func (ws *writeScheduler) takeFrom(id uint32, q *writeQueue) frameWriteMsg {
	wm := q.shift()
	if q.empty() {
		// TODO: reclaim its slice and use it for future allocations
		// in the writeScheduler.streamQueue method above when making
		// the writeQueue.
		delete(ws.sq, id)
	}
	return wm
}

type writeQueue struct {
	s []frameWriteMsg
}

func (q *writeQueue) empty() bool { return len(q.s) == 0 }

func (q *writeQueue) push(wm frameWriteMsg) {
	q.s = append(q.s, wm)
}

func (q *writeQueue) shift() frameWriteMsg {
	if len(q.s) == 0 {
		panic("invalid use of queue")
	}
	wm := q.s[0]
	// TODO: less copy-happy queue.
	copy(q.s, q.s[1:])
	q.s[len(q.s)-1] = frameWriteMsg{}
	q.s = q.s[:len(q.s)-1]
	return wm
}

func (q *writeQueue) firstIsNoCost() bool { return q.s[0].cost == 0 }
<|endoftext|>


<commit_before>package katool

//---------------------------------------------------------------------------
// Package factored import statement:
//---------------------------------------------------------------------------

import (

	// Stdlib:
	"encoding/json"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"strconv"
	"strings"
)

//-----------------------------------------------------------------------------
// func: ExecutePipeline
//-----------------------------------------------------------------------------

// ExecutePipeline takes two commands and pipes the stdout of the first one
// into the stdin of the second one.
func ExecutePipeline(cmd1, cmd2 *exec.Cmd) error {

	var err error

	// Adjust the stderr:
	cmd1.Stderr = os.Stderr
	cmd2.Stderr = os.Stderr

	// Connect both commands:
	cmd2.Stdin, err = cmd1.StdoutPipe()
	if err != nil {
		return err
	}

	// Execute the pipeline:
	if err := cmd2.Start(); err != nil {
		return err
	}
	if err := cmd1.Run(); err != nil {
		return err
	}
	if err := cmd2.Wait(); err != nil {
		return err
	}

	// Return on success:
	return nil
}

//-----------------------------------------------------------------------------
// func: EtcdToken
//-----------------------------------------------------------------------------

// EtcdToken takes masterCount and returns a valid etcd bootstrap token:
func EtcdToken(masterCount int) (string, error) {

	// Request an etcd bootstrap token:
	res, err := http.Get("https://discovery.etcd.io/new?size=" + strconv.Itoa(masterCount))
	if err != nil {
		return "", err
	}

	// Retrieve the token URL:
	tokenURL, err := ioutil.ReadAll(res.Body)
	res.Body.Close()
	if err != nil {
		return "", err
	}

	// Return the token ID:
	slice := strings.Split(string(tokenURL), "/")
	return slice[len(slice)-1], nil
}

//-----------------------------------------------------------------------------
// func: LoadState
//-----------------------------------------------------------------------------

// LoadState reads the current ClusterID state file and decodes its content
// into a data structure:
func LoadState(clusterID string) (map[string]interface{}, error) {

	// Load data from state file:
	state_file := os.Getenv("HOME") + "/.kato/" + clusterID + ".json"
	raw, err := ioutil.ReadFile(state_file)
	if err != nil {
		return nil, err
	}

	// Decode the loaded JSON data:
	var dat map[string]interface{}
	if err := json.Unmarshal(raw, &dat); err != nil {
		return nil, err
	}

	return dat, nil
}
<commit_msg>Fix don't use underscores in Go names<commit_after>package katool

//---------------------------------------------------------------------------
// Package factored import statement:
//---------------------------------------------------------------------------

import (

	// Stdlib:
	"encoding/json"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"strconv"
	"strings"
)

//-----------------------------------------------------------------------------
// func: ExecutePipeline
//-----------------------------------------------------------------------------

// ExecutePipeline takes two commands and pipes the stdout of the first one
// into the stdin of the second one.
func ExecutePipeline(cmd1, cmd2 *exec.Cmd) error {

	var err error

	// Adjust the stderr:
	cmd1.Stderr = os.Stderr
	cmd2.Stderr = os.Stderr

	// Connect both commands:
	cmd2.Stdin, err = cmd1.StdoutPipe()
	if err != nil {
		return err
	}

	// Execute the pipeline:
	if err := cmd2.Start(); err != nil {
		return err
	}
	if err := cmd1.Run(); err != nil {
		return err
	}
	if err := cmd2.Wait(); err != nil {
		return err
	}

	// Return on success:
	return nil
}

//-----------------------------------------------------------------------------
// func: EtcdToken
//-----------------------------------------------------------------------------

// EtcdToken takes masterCount and returns a valid etcd bootstrap token:
func EtcdToken(masterCount int) (string, error) {

	// Request an etcd bootstrap token:
	res, err := http.Get("https://discovery.etcd.io/new?size=" + strconv.Itoa(masterCount))
	if err != nil {
		return "", err
	}

	// Retrieve the token URL:
	tokenURL, err := ioutil.ReadAll(res.Body)
	res.Body.Close()
	if err != nil {
		return "", err
	}

	// Return the token ID:
	slice := strings.Split(string(tokenURL), "/")
	return slice[len(slice)-1], nil
}

//-----------------------------------------------------------------------------
// func: LoadState
//-----------------------------------------------------------------------------

// LoadState reads the current ClusterID state file and decodes its content
// into a data structure:
func LoadState(clusterID string) (map[string]interface{}, error) {

	// Load data from state file:
	stateFile := os.Getenv("HOME") + "/.kato/" + clusterID + ".json"
	raw, err := ioutil.ReadFile(stateFile)
	if err != nil {
		return nil, err
	}

	// Decode the loaded JSON data:
	var dat map[string]interface{}
	if err := json.Unmarshal(raw, &dat); err != nil {
		return nil, err
	}

	return dat, nil
}
<|endoftext|>


<commit_before>// +build !clustered,!gcloud

package dvid

import (
	"fmt"
	"log"

	"gopkg.in/natefinch/lumberjack.v2"
)

type stdLogger struct {
	*lumberjack.Logger
}

var logger stdLogger

type LogConfig struct {
	Logfile string
	MaxSize int `toml:"max_log_size"`
	MaxAge  int `toml:"max_log_age"`
}

// SetLogger creates a logger that saves to a rotating log file.
func (c *LogConfig) SetLogger() {
	if c.Logfile == "" {
		fmt.Println("Sending log messages to stdout since no log file specified.")
		return
	}
	fmt.Printf("Sending log messages to: %s\n", c.Logfile)
	l := &lumberjack.Logger{
		Filename: c.Logfile,
		MaxSize:  c.MaxSize, // megabytes
		MaxAge:   c.MaxAge,  //days
	}
	log.SetOutput(l)
}

// --- Logger implementation ----

// Debugf formats its arguments analogous to fmt.Printf and records the text as a log
// message at Debug level.  If dvid.Verbose is not true, these logs aren't written.
func (slog stdLogger) Debugf(format string, args ...interface{}) {
	log.Printf("   DEBUG "+format, args...)
}

// Infof is like Debugf, but at Info level and will be written regardless if not in
// verbose mode.
func (slog stdLogger) Infof(format string, args ...interface{}) {
	log.Printf("    INFO "+format, args...)
}

// Warningf is like Debugf, but at Warning level.
func (slog stdLogger) Warningf(format string, args ...interface{}) {
	log.Printf(" WARNING "+format, args...)
}

// Errorf is like Debugf, but at Error level.
func (slog stdLogger) Errorf(format string, args ...interface{}) {
	log.Printf("  ERROR "+format, args...)
}

// Criticalf is like Debugf, but at Critical level.
func (slog stdLogger) Criticalf(format string, args ...interface{}) {
	log.Printf("CRITICAL "+format, args...)
}

func (slog stdLogger) Shutdown() {
	slog.Rotate()
}
<commit_msg>Use stdout for logging if no config file<commit_after>// +build !clustered,!gcloud

package dvid

import (
	"fmt"
	"log"

	"gopkg.in/natefinch/lumberjack.v2"
)

type stdLogger struct {
	*lumberjack.Logger
}

var logger stdLogger

type LogConfig struct {
	Logfile string
	MaxSize int `toml:"max_log_size"`
	MaxAge  int `toml:"max_log_age"`
}

// SetLogger creates a logger that saves to a rotating log file.
func (c *LogConfig) SetLogger() {
	if c == nil || c.Logfile == "" {
		Infof("Sending log messages to stdout since no log file specified.")
		return
	}
	fmt.Printf("Sending log messages to: %s\n", c.Logfile)
	l := &lumberjack.Logger{
		Filename: c.Logfile,
		MaxSize:  c.MaxSize, // megabytes
		MaxAge:   c.MaxAge,  //days
	}
	log.SetOutput(l)
}

// --- Logger implementation ----

// Debugf formats its arguments analogous to fmt.Printf and records the text as a log
// message at Debug level.  If dvid.Verbose is not true, these logs aren't written.
func (slog stdLogger) Debugf(format string, args ...interface{}) {
	log.Printf("   DEBUG "+format, args...)
}

// Infof is like Debugf, but at Info level and will be written regardless if not in
// verbose mode.
func (slog stdLogger) Infof(format string, args ...interface{}) {
	log.Printf("    INFO "+format, args...)
}

// Warningf is like Debugf, but at Warning level.
func (slog stdLogger) Warningf(format string, args ...interface{}) {
	log.Printf(" WARNING "+format, args...)
}

// Errorf is like Debugf, but at Error level.
func (slog stdLogger) Errorf(format string, args ...interface{}) {
	log.Printf("  ERROR "+format, args...)
}

// Criticalf is like Debugf, but at Critical level.
func (slog stdLogger) Criticalf(format string, args ...interface{}) {
	log.Printf("CRITICAL "+format, args...)
}

func (slog stdLogger) Shutdown() {
	slog.Rotate()
}
<|endoftext|>


<commit_before>package edn

import . "testing"

func assertLexerYieldsCorrectTokens(
	t *T,
	source string,
	types []tokenType,
	values []string) {

	if len(types) != len(values) {
		t.Error("Expecting equal number of types and values")
		return
	}

	tokens := make([]token, 0)

	for token := range Lex(source).tokens {
		tokens = append(tokens, token)
	}

	if len(tokens) != len(types) {
		t.Errorf("Got %d tokens, expecting %d", len(tokens), len(types))
		return
	}

	for i, actual := range tokens {
		expected := token{
			kind:  types[i],
			value: values[i],
		}

		if actual != expected {
			t.Errorf("Expecting %#v; actual %#v", expected, actual)
		}
	}
}

func tokens(tokens ...tokenType) []tokenType {
	return tokens
}
func values(values ...string) []string {
	return values
}

func TestEmptyGivesOnlyEOF(t *T) {
	assertLexerYieldsCorrectTokens(t,
		"",
		tokens(tEOF),
		values(""))
}

func TestOpenCloseLists(t *T) {
	assertLexerYieldsCorrectTokens(t,
		"()",
		tokens(tOpenList, tCloseList, tEOF),
		values("(", ")", ""))
}

func TestComplex(t *T) {
	assertLexerYieldsCorrectTokens(t,
		"(1, 24223 ; i'm a comment\n 0 -4 {[5] #{2.34} \"ab\\\"c\"} '())",
		tokens(
			tOpenList, tNumber, tNumber, tComment, tNumber, tNumber,
			tOpenMap, tOpenVector, tNumber, tCloseVector, tOpenSet, tNumber,
			tCloseMapOrSet, tString, tCloseMapOrSet, tQuoteNextForm,
			tOpenList, tCloseList, tCloseList, tEOF),
		values("(", "1", "24223", "; i'm a comment", "0", "-4", "{",
			"[", "5", "]", "#{", "2.34", "}", "\"ab\\\"c\"", "}", "'",
			"(", ")", ")", ""))
}
<commit_msg>More debug information on test failure<commit_after>package edn

import . "testing"

func assertLexerYieldsCorrectTokens(
	t *T,
	source string,
	types []tokenType,
	values []string) {

	if len(types) != len(values) {
		t.Error("Expecting equal number of types and values")
		return
	}

	tokens := make([]token, 0)

	for token := range Lex(source).tokens {
		tokens = append(tokens, token)
	}

	if len(tokens) != len(types) {
		t.Errorf("Got %d tokens, expecting %d:\n\n%#v\n%#v",
			len(tokens),
			len(values),
			tokens, values)
		return
	}

	for i, actual := range tokens {
		expected := token{
			kind:  types[i],
			value: values[i],
		}

		if actual != expected {
			t.Errorf("Expecting %#v; actual %#v", expected, actual)
		}
	}
}

func tokens(tokens ...tokenType) []tokenType {
	return tokens
}
func values(values ...string) []string {
	return values
}

func TestEmptyGivesOnlyEOF(t *T) {
	assertLexerYieldsCorrectTokens(t,
		"",
		tokens(tEOF),
		values(""))
}

func TestOpenCloseLists(t *T) {
	assertLexerYieldsCorrectTokens(t,
		"()",
		tokens(tOpenList, tCloseList, tEOF),
		values("(", ")", ""))
}

func TestComplex(t *T) {
	assertLexerYieldsCorrectTokens(t,
		"(1, 24223 ; i'm a comment\n 0 -4 {[5] #{2.34} \"ab\\\"c\"} '())",
		tokens(
			tOpenList, tNumber, tNumber, tComment, tNumber, tNumber,
			tOpenMap, tOpenVector, tNumber, tCloseVector, tOpenSet, tNumber,
			tCloseMapOrSet, tString, tCloseMapOrSet, tQuoteNextForm,
			tOpenList, tCloseList, tCloseList, tEOF),
		values("(", "1", "24223", "; i'm a comment", "0", "-4", "{",
			"[", "5", "]", "#{", "2.34", "}", "\"ab\\\"c\"", "}", "'",
			"(", ")", ")", ""))
}
<|endoftext|>


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

package procfs

import (
	"bufio"
	"errors"
	"os"
	"sort"
	"strconv"
	"strings"
)

// NetDevLine is single line parsed from /proc/net/dev or /proc/[pid]/net/dev.
type NetDevLine struct {
	Name         string `json:"name"`          // The name of the interface.
	RxBytes      uint64 `json:"rx_bytes"`      // Cumulative count of bytes received.
	RxPackets    uint64 `json:"rx_packets"`    // Cumulative count of packets received.
	RxErrors     uint64 `json:"rx_errors"`     // Cumulative count of receive errors encountered.
	RxDropped    uint64 `json:"rx_dropped"`    // Cumulative count of packets dropped while receiving.
	RxFIFO       uint64 `json:"rx_fifo"`       // Cumulative count of FIFO buffer errors.
	RxFrame      uint64 `json:"rx_frame"`      // Cumulative count of packet framing errors.
	RxCompressed uint64 `json:"rx_compressed"` // Cumulative count of compressed packets received by the device driver.
	RxMulticast  uint64 `json:"rx_multicast"`  // Cumulative count of multicast frames received by the device driver.
	TxBytes      uint64 `json:"tx_bytes"`      // Cumulative count of bytes transmitted.
	TxPackets    uint64 `json:"tx_packets"`    // Cumulative count of packets transmitted.
	TxErrors     uint64 `json:"tx_errors"`     // Cumulative count of transmit errors encountered.
	TxDropped    uint64 `json:"tx_dropped"`    // Cumulative count of packets dropped while transmitting.
	TxFIFO       uint64 `json:"tx_fifo"`       // Cumulative count of FIFO buffer errors.
	TxCollisions uint64 `json:"tx_collisions"` // Cumulative count of collisions detected on the interface.
	TxCarrier    uint64 `json:"tx_carrier"`    // Cumulative count of carrier losses detected by the device driver.
	TxCompressed uint64 `json:"tx_compressed"` // Cumulative count of compressed packets transmitted by the device driver.
}

// NetDev is parsed from /proc/net/dev or /proc/[pid]/net/dev. The map keys
// are interface names.
type NetDev map[string]NetDevLine

// NewNetDev returns kernel/system statistics read from /proc/net/dev.
func NewNetDev() (NetDev, error) {
	fs, err := NewFS(DefaultMountPoint)
	if err != nil {
		return nil, err
	}

	return fs.NewNetDev()
}

// NewNetDev returns kernel/system statistics read from /proc/net/dev.
func (fs FS) NewNetDev() (NetDev, error) {
	return newNetDev(fs.Path("net/dev"))
}

// NewNetDev returns kernel/system statistics read from /proc/[pid]/net/dev.
func (p Proc) NewNetDev() (NetDev, error) {
	return newNetDev(p.path("net/dev"))
}

// newNetDev creates a new NetDev from the contents of the given file.
func newNetDev(file string) (NetDev, error) {
	f, err := os.Open(file)
	if err != nil {
		return NetDev{}, err
	}
	defer f.Close()

	nd := NetDev{}
	s := bufio.NewScanner(f)
	for n := 0; s.Scan(); n++ {
		// Skip the 2 header lines.
		if n < 2 {
			continue
		}

		line, err := nd.parseLine(s.Text())
		if err != nil {
			return nd, err
		}

		nd[line.Name] = *line
	}

	return nd, s.Err()
}

// parseLine parses a single line from the /proc/net/dev file. Header lines
// must be filtered prior to calling this method.
func (nd NetDev) parseLine(rawLine string) (*NetDevLine, error) {
	parts := strings.SplitN(rawLine, ":", 2)
	if len(parts) != 2 {
		return nil, errors.New("invalid net/dev line, missing colon")
	}
	fields := strings.Fields(strings.TrimSpace(parts[1]))

	var err error
	line := &NetDevLine{}

	// Interface Name
	line.Name = strings.TrimSpace(parts[0])
	if line.Name == "" {
		return nil, errors.New("invalid net/dev line, empty interface name")
	}

	// RX
	line.RxBytes, err = strconv.ParseUint(fields[0], 10, 64)
	if err != nil {
		return nil, err
	}
	line.RxPackets, err = strconv.ParseUint(fields[1], 10, 64)
	if err != nil {
		return nil, err
	}
	line.RxErrors, err = strconv.ParseUint(fields[2], 10, 64)
	if err != nil {
		return nil, err
	}
	line.RxDropped, err = strconv.ParseUint(fields[3], 10, 64)
	if err != nil {
		return nil, err
	}
	line.RxFIFO, err = strconv.ParseUint(fields[4], 10, 64)
	if err != nil {
		return nil, err
	}
	line.RxFrame, err = strconv.ParseUint(fields[5], 10, 64)
	if err != nil {
		return nil, err
	}
	line.RxCompressed, err = strconv.ParseUint(fields[6], 10, 64)
	if err != nil {
		return nil, err
	}
	line.RxMulticast, err = strconv.ParseUint(fields[7], 10, 64)
	if err != nil {
		return nil, err
	}

	// TX
	line.TxBytes, err = strconv.ParseUint(fields[8], 10, 64)
	if err != nil {
		return nil, err
	}
	line.TxPackets, err = strconv.ParseUint(fields[9], 10, 64)
	if err != nil {
		return nil, err
	}
	line.TxErrors, err = strconv.ParseUint(fields[10], 10, 64)
	if err != nil {
		return nil, err
	}
	line.TxDropped, err = strconv.ParseUint(fields[11], 10, 64)
	if err != nil {
		return nil, err
	}
	line.TxFIFO, err = strconv.ParseUint(fields[12], 10, 64)
	if err != nil {
		return nil, err
	}
	line.TxCollisions, err = strconv.ParseUint(fields[13], 10, 64)
	if err != nil {
		return nil, err
	}
	line.TxCarrier, err = strconv.ParseUint(fields[14], 10, 64)
	if err != nil {
		return nil, err
	}
	line.TxCompressed, err = strconv.ParseUint(fields[15], 10, 64)
	if err != nil {
		return nil, err
	}

	return line, nil
}

// Total aggregates the values across interfaces and returns a new NetDevLine.
// The Name field will be a sorted comma seperated list of interface names.
func (nd NetDev) Total() NetDevLine {
	total := NetDevLine{}

	names := make([]string, 0, len(nd))
	for _, ifc := range nd {
		names = append(names, ifc.Name)
		total.RxBytes += ifc.RxBytes
		total.RxPackets += ifc.RxPackets
		total.RxPackets += ifc.RxPackets
		total.RxErrors += ifc.RxErrors
		total.RxDropped += ifc.RxDropped
		total.RxFIFO += ifc.RxFIFO
		total.RxFrame += ifc.RxFrame
		total.RxCompressed += ifc.RxCompressed
		total.RxMulticast += ifc.RxMulticast
		total.TxBytes += ifc.TxBytes
		total.TxPackets += ifc.TxPackets
		total.TxErrors += ifc.TxErrors
		total.TxDropped += ifc.TxDropped
		total.TxFIFO += ifc.TxFIFO
		total.TxCollisions += ifc.TxCollisions
		total.TxCarrier += ifc.TxCarrier
		total.TxCompressed += ifc.TxCompressed
	}
	sort.Strings(names)
	total.Name = strings.Join(names, ", ")

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

package procfs

import (
	"bufio"
	"errors"
	"os"
	"sort"
	"strconv"
	"strings"
)

// NetDevLine is single line parsed from /proc/net/dev or /proc/[pid]/net/dev.
type NetDevLine struct {
	Name         string `json:"name"`          // The name of the interface.
	RxBytes      uint64 `json:"rx_bytes"`      // Cumulative count of bytes received.
	RxPackets    uint64 `json:"rx_packets"`    // Cumulative count of packets received.
	RxErrors     uint64 `json:"rx_errors"`     // Cumulative count of receive errors encountered.
	RxDropped    uint64 `json:"rx_dropped"`    // Cumulative count of packets dropped while receiving.
	RxFIFO       uint64 `json:"rx_fifo"`       // Cumulative count of FIFO buffer errors.
	RxFrame      uint64 `json:"rx_frame"`      // Cumulative count of packet framing errors.
	RxCompressed uint64 `json:"rx_compressed"` // Cumulative count of compressed packets received by the device driver.
	RxMulticast  uint64 `json:"rx_multicast"`  // Cumulative count of multicast frames received by the device driver.
	TxBytes      uint64 `json:"tx_bytes"`      // Cumulative count of bytes transmitted.
	TxPackets    uint64 `json:"tx_packets"`    // Cumulative count of packets transmitted.
	TxErrors     uint64 `json:"tx_errors"`     // Cumulative count of transmit errors encountered.
	TxDropped    uint64 `json:"tx_dropped"`    // Cumulative count of packets dropped while transmitting.
	TxFIFO       uint64 `json:"tx_fifo"`       // Cumulative count of FIFO buffer errors.
	TxCollisions uint64 `json:"tx_collisions"` // Cumulative count of collisions detected on the interface.
	TxCarrier    uint64 `json:"tx_carrier"`    // Cumulative count of carrier losses detected by the device driver.
	TxCompressed uint64 `json:"tx_compressed"` // Cumulative count of compressed packets transmitted by the device driver.
}

// NetDev is parsed from /proc/net/dev or /proc/[pid]/net/dev. The map keys
// are interface names.
type NetDev map[string]NetDevLine

// NewNetDev returns kernel/system statistics read from /proc/net/dev.
func NewNetDev() (NetDev, error) {
	fs, err := NewFS(DefaultMountPoint)
	if err != nil {
		return nil, err
	}

	return fs.NewNetDev()
}

// NewNetDev returns kernel/system statistics read from /proc/net/dev.
func (fs FS) NewNetDev() (NetDev, error) {
	return newNetDev(fs.Path("net/dev"))
}

// NewNetDev returns kernel/system statistics read from /proc/[pid]/net/dev.
func (p Proc) NewNetDev() (NetDev, error) {
	return newNetDev(p.path("net/dev"))
}

// newNetDev creates a new NetDev from the contents of the given file.
func newNetDev(file string) (NetDev, error) {
	f, err := os.Open(file)
	if err != nil {
		return NetDev{}, err
	}
	defer f.Close()

	nd := NetDev{}
	s := bufio.NewScanner(f)
	for n := 0; s.Scan(); n++ {
		// Skip the 2 header lines.
		if n < 2 {
			continue
		}

		line, err := nd.parseLine(s.Text())
		if err != nil {
			return nd, err
		}

		nd[line.Name] = *line
	}

	return nd, s.Err()
}

// parseLine parses a single line from the /proc/net/dev file. Header lines
// must be filtered prior to calling this method.
func (nd NetDev) parseLine(rawLine string) (*NetDevLine, error) {
	parts := strings.SplitN(rawLine, ":", 2)
	if len(parts) != 2 {
		return nil, errors.New("invalid net/dev line, missing colon")
	}
	fields := strings.Fields(strings.TrimSpace(parts[1]))

	var err error
	line := &NetDevLine{}

	// Interface Name
	line.Name = strings.TrimSpace(parts[0])
	if line.Name == "" {
		return nil, errors.New("invalid net/dev line, empty interface name")
	}

	// RX
	line.RxBytes, err = strconv.ParseUint(fields[0], 10, 64)
	if err != nil {
		return nil, err
	}
	line.RxPackets, err = strconv.ParseUint(fields[1], 10, 64)
	if err != nil {
		return nil, err
	}
	line.RxErrors, err = strconv.ParseUint(fields[2], 10, 64)
	if err != nil {
		return nil, err
	}
	line.RxDropped, err = strconv.ParseUint(fields[3], 10, 64)
	if err != nil {
		return nil, err
	}
	line.RxFIFO, err = strconv.ParseUint(fields[4], 10, 64)
	if err != nil {
		return nil, err
	}
	line.RxFrame, err = strconv.ParseUint(fields[5], 10, 64)
	if err != nil {
		return nil, err
	}
	line.RxCompressed, err = strconv.ParseUint(fields[6], 10, 64)
	if err != nil {
		return nil, err
	}
	line.RxMulticast, err = strconv.ParseUint(fields[7], 10, 64)
	if err != nil {
		return nil, err
	}

	// TX
	line.TxBytes, err = strconv.ParseUint(fields[8], 10, 64)
	if err != nil {
		return nil, err
	}
	line.TxPackets, err = strconv.ParseUint(fields[9], 10, 64)
	if err != nil {
		return nil, err
	}
	line.TxErrors, err = strconv.ParseUint(fields[10], 10, 64)
	if err != nil {
		return nil, err
	}
	line.TxDropped, err = strconv.ParseUint(fields[11], 10, 64)
	if err != nil {
		return nil, err
	}
	line.TxFIFO, err = strconv.ParseUint(fields[12], 10, 64)
	if err != nil {
		return nil, err
	}
	line.TxCollisions, err = strconv.ParseUint(fields[13], 10, 64)
	if err != nil {
		return nil, err
	}
	line.TxCarrier, err = strconv.ParseUint(fields[14], 10, 64)
	if err != nil {
		return nil, err
	}
	line.TxCompressed, err = strconv.ParseUint(fields[15], 10, 64)
	if err != nil {
		return nil, err
	}

	return line, nil
}

// Total aggregates the values across interfaces and returns a new NetDevLine.
// The Name field will be a sorted comma separated list of interface names.
func (nd NetDev) Total() NetDevLine {
	total := NetDevLine{}

	names := make([]string, 0, len(nd))
	for _, ifc := range nd {
		names = append(names, ifc.Name)
		total.RxBytes += ifc.RxBytes
		total.RxPackets += ifc.RxPackets
		total.RxPackets += ifc.RxPackets
		total.RxErrors += ifc.RxErrors
		total.RxDropped += ifc.RxDropped
		total.RxFIFO += ifc.RxFIFO
		total.RxFrame += ifc.RxFrame
		total.RxCompressed += ifc.RxCompressed
		total.RxMulticast += ifc.RxMulticast
		total.TxBytes += ifc.TxBytes
		total.TxPackets += ifc.TxPackets
		total.TxErrors += ifc.TxErrors
		total.TxDropped += ifc.TxDropped
		total.TxFIFO += ifc.TxFIFO
		total.TxCollisions += ifc.TxCollisions
		total.TxCarrier += ifc.TxCarrier
		total.TxCompressed += ifc.TxCompressed
	}
	sort.Strings(names)
	total.Name = strings.Join(names, ", ")

	return total
}
<|endoftext|>


<commit_before><commit_msg>Clarify possible options for defaultEndpoint in validation (#32146)<commit_after><|endoftext|>


<commit_before>package oauth

import (
	"io/ioutil"
	"log"
	"os"
	"testing"

	"github.com/RichardKnop/go-oauth2-server/config"
	"github.com/RichardKnop/go-oauth2-server/migrations"
	"github.com/areatech/go-fixtures"
	"github.com/jinzhu/gorm"
	"github.com/stretchr/testify/suite"
	// sqlite driver
	_ "github.com/mattn/go-sqlite3"
)

var testDbPath = "/tmp/oauth_testdb.sqlite"

// OauthTestSuite needs to be exported so the tests run
type OauthTestSuite struct {
	suite.Suite
	cnf     *config.Config
	db      *gorm.DB
	service *Service
	client  *Client
	user    *User
}

// The SetupSuite method will be run by testify once, at the very
// start of the testing suite, before any tests are run.
func (suite *OauthTestSuite) SetupSuite() {
	// Delete the test database
	os.Remove(testDbPath)

	// Initialise the config
	suite.cnf = config.NewConfig()

	// Init in-memory test database
	inMemoryDB, err := gorm.Open("sqlite3", testDbPath)
	if err != nil {
		log.Fatal(err)
	}
	suite.db = &inMemoryDB

	// Run all migrations
	if err := migrations.Bootstrap(suite.db); err != nil {
		log.Print(err)
	}
	if err := MigrateAll(suite.db); err != nil {
		log.Print(err)
	}

	// Load test data from fixtures
	for _, path := range []string{
		"../fixtures/test_data.yml",
	} {
		// Read fixture data from the file
		data, err := ioutil.ReadFile(path)
		if err != nil {
			log.Fatal(err)
		}

		// Insert the fixture data
		if err := fixtures.Load(data, suite.db.DB(), suite.cnf.Database.Type); err != nil {
			log.Fatal(err)
		}
	}

	// Fetch the test client
	suite.client = new(Client)
	if err := suite.db.First(suite.client, 1).Error; err != nil {
		log.Fatal(err)
	}

	// Fetch the test user
	suite.user = new(User)
	if err := suite.db.First(suite.user, 1).Error; err != nil {
		log.Fatal(err)
	}

	// Initialise the service
	suite.service = NewService(suite.cnf, suite.db)
}

// The TearDownSuite method will be run by testify once, at the very
// end of the testing suite, after all tests have been run.
func (suite *OauthTestSuite) TearDownSuite() {
	//
}

// The SetupTest method will be run before every test in the suite.
func (suite *OauthTestSuite) SetupTest() {
	//
}

// The TearDownTest method will be run after every test in the suite.
func (suite *OauthTestSuite) TearDownTest() {
	// Scopes are static, populated from fixtures,
	// so there is no need to clear them after running a test
	suite.db.Unscoped().Delete(AuthorizationCode{})
	suite.db.Unscoped().Delete(RefreshToken{})
	suite.db.Unscoped().Delete(AccessToken{})
	suite.db.Unscoped().Not("id", suite.user.ID).Delete(User{})
	suite.db.Unscoped().Not("id", suite.client.ID).Delete(Client{})
}

// TestOauthTestSuite ...
// In order for 'go test' to run this suite, we need to create
// a normal test function and pass our suite to suite.Run
func TestOauthTestSuite(t *testing.T) {
	suite.Run(t, new(OauthTestSuite))
}
<commit_msg>Update suite_test.go<commit_after>package oauth

import (
	"io/ioutil"
	"log"
	"os"
	"testing"

	"github.com/RichardKnop/go-oauth2-server/config"
	"github.com/RichardKnop/go-oauth2-server/migrations"
	"github.com/areatech/go-fixtures"
	"github.com/jinzhu/gorm"
	"github.com/stretchr/testify/suite"
	// sqlite driver
	_ "github.com/mattn/go-sqlite3"
)

var testDbPath = "/tmp/oauth_testdb.sqlite"

// OauthTestSuite needs to be exported so the tests run
type OauthTestSuite struct {
	suite.Suite
	cnf     *config.Config
	db      *gorm.DB
	service *Service
	client  *Client
	user    *User
}

// The SetupSuite method will be run by testify once, at the very
// start of the testing suite, before any tests are run.
func (suite *OauthTestSuite) SetupSuite() {
	// Delete the test database
	os.Remove(testDbPath)

	// Initialise the config
	suite.cnf = config.NewConfig()

	// Init in-memory test database
	inMemoryDB, err := gorm.Open("sqlite3", testDbPath)
	if err != nil {
		log.Fatal(err)
	}
	suite.db = &inMemoryDB

	// Run all migrations
	if err := migrations.Bootstrap(suite.db); err != nil {
		log.Print(err)
	}
	if err := MigrateAll(suite.db); err != nil {
		log.Print(err)
	}

	// Load test data from fixtures
	for _, path := range []string{
		"../fixtures/test_data.yml",
	} {
		// Read fixture data from the file
		data, err := ioutil.ReadFile(path)
		if err != nil {
			log.Fatal(err)
		}

		// Insert the fixture data
		err = fixtures.Load(data, suite.db.DB(), suite.cnf.Database.Type)
		if err != nil {
			log.Fatal(err)
		}
	}

	// Fetch the test client
	suite.client = new(Client)
	if err := suite.db.First(suite.client, 1).Error; err != nil {
		log.Fatal(err)
	}

	// Fetch the test user
	suite.user = new(User)
	if err := suite.db.First(suite.user, 1).Error; err != nil {
		log.Fatal(err)
	}

	// Initialise the service
	suite.service = NewService(suite.cnf, suite.db)
}

// The TearDownSuite method will be run by testify once, at the very
// end of the testing suite, after all tests have been run.
func (suite *OauthTestSuite) TearDownSuite() {
	//
}

// The SetupTest method will be run before every test in the suite.
func (suite *OauthTestSuite) SetupTest() {
	//
}

// The TearDownTest method will be run after every test in the suite.
func (suite *OauthTestSuite) TearDownTest() {
	// Scopes are static, populated from fixtures,
	// so there is no need to clear them after running a test
	suite.db.Unscoped().Delete(AuthorizationCode{})
	suite.db.Unscoped().Delete(RefreshToken{})
	suite.db.Unscoped().Delete(AccessToken{})
	suite.db.Unscoped().Not("id", suite.user.ID).Delete(User{})
	suite.db.Unscoped().Not("id", suite.client.ID).Delete(Client{})
}

// TestOauthTestSuite ...
// In order for 'go test' to run this suite, we need to create
// a normal test function and pass our suite to suite.Run
func TestOauthTestSuite(t *testing.T) {
	suite.Run(t, new(OauthTestSuite))
}
<|endoftext|>


<commit_before>package pay

import (
	"bytes"
	"crypto/hmac"
	"crypto/md5"
	"crypto/sha256"
	"encoding/hex"
	"encoding/xml"
	"errors"
	"hash"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/silenceper/wechat/context"
	"github.com/silenceper/wechat/util"
)

var payGateway = "https://api.mch.weixin.qq.com/pay/unifiedorder"

// Pay struct extends context
type Pay struct {
	*context.Context
}

// Params was NEEDED when request unifiedorder
// 传入的参数，用于生成 prepay_id 的必需参数
type Params struct {
	TotalFee   string
	CreateIP   string
	Body       string
	OutTradeNo string
	OpenID     string
	TradeType  string
	SignType   string
	Detail     string
	Attach     string
	GoodsTag   string
	NotifyURL  string
}

// Config 是传出用于 js sdk 用的参数
type Config struct {
	Timestamp string `json:"timestamp"`
	NonceStr  string `json:"nonceStr"`
	PrePayID  string `json:"prePayId"`
	SignType  string `json:"signType"`
	Package   string `json:"package"`
	PaySign   string `json:"paySign"`
}

// PreOrder 是 unifie order 接口的返回
type PreOrder struct {
	ReturnCode string `xml:"return_code"`
	ReturnMsg  string `xml:"return_msg"`
	AppID      string `xml:"appid,omitempty"`
	MchID      string `xml:"mch_id,omitempty"`
	NonceStr   string `xml:"nonce_str,omitempty"`
	Sign       string `xml:"sign,omitempty"`
	ResultCode string `xml:"result_code,omitempty"`
	TradeType  string `xml:"trade_type,omitempty"`
	PrePayID   string `xml:"prepay_id,omitempty"`
	CodeURL    string `xml:"code_url,omitempty"`
	ErrCode    string `xml:"err_code,omitempty"`
	ErrCodeDes string `xml:"err_code_des,omitempty"`
}

// payRequest 接口请求参数
type payRequest struct {
	AppID          string `xml:"appid"`
	MchID          string `xml:"mch_id"`
	DeviceInfo     string `xml:"device_info,omitempty"`
	NonceStr       string `xml:"nonce_str"`
	Sign           string `xml:"sign"`
	SignType       string `xml:"sign_type,omitempty"`
	Body           string `xml:"body"`
	Detail         string `xml:"detail,omitempty"`
	Attach         string `xml:"attach,omitempty"`      // 附加数据
	OutTradeNo     string `xml:"out_trade_no"`          // 商户订单号
	FeeType        string `xml:"fee_type,omitempty"`    // 标价币种
	TotalFee       string `xml:"total_fee"`             // 标价金额
	SpbillCreateIP string `xml:"spbill_create_ip"`      // 终端IP
	TimeStart      string `xml:"time_start,omitempty"`  // 交易起始时间
	TimeExpire     string `xml:"time_expire,omitempty"` // 交易结束时间
	GoodsTag       string `xml:"goods_tag,omitempty"`   // 订单优惠标记
	NotifyURL      string `xml:"notify_url"`            // 通知地址
	TradeType      string `xml:"trade_type"`            // 交易类型
	ProductID      string `xml:"product_id,omitempty"`  // 商品ID
	LimitPay       string `xml:"limit_pay,omitempty"`   //
	OpenID         string `xml:"openid,omitempty"`      // 用户标识
	SceneInfo      string `xml:"scene_info,omitempty"`  // 场景信息
}

// NewPay return an instance of Pay package
func NewPay(ctx *context.Context) *Pay {
	pay := Pay{Context: ctx}
	return &pay
}

// BridgeConfig get js bridge config
func (pcf *Pay) BridgeConfig(p *Params) (cfg Config, err error) {
	var (
		buffer    strings.Builder
		h         hash.Hash
		timestamp = strconv.FormatInt(time.Now().Unix(), 10)
	)
	order, err := pcf.PrePayOrder(p)
	if err != nil {
		return
	}
	if p.SignType == "" {
		p.SignType = "MD5"
	}
	buffer.WriteString("appId=")
	buffer.WriteString(order.AppID)
	buffer.WriteString("&nonceStr=")
	buffer.WriteString(order.NonceStr)
	buffer.WriteString("&package=")
	buffer.WriteString("prepay_id=" + order.PrePayID)
	buffer.WriteString("&signType=")
	buffer.WriteString(p.SignType)
	buffer.WriteString("&timeStamp=")
	buffer.WriteString(timestamp)
	buffer.WriteString("&key=")
	buffer.WriteString(pcf.PayKey)
	if p.SignType == "MD5" {
		h = md5.New()
	} else {
		h = hmac.New(sha256.New, []byte(pcf.PayKey))
	}
	h.Write([]byte(buffer.String()))
	// 签名
	cfg.PaySign = strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
	cfg.NonceStr = order.NonceStr
	cfg.Timestamp = timestamp
	cfg.PrePayID = order.PrePayID
	cfg.SignType = p.SignType
	cfg.Package = "prepay_id=" + order.PrePayID
	return
}

// PrePayOrder return data for invoke wechat payment
func (pcf *Pay) PrePayOrder(p *Params) (payOrder PreOrder, err error) {
	nonceStr := util.RandomStr(32)
	param := make(map[string]interface{})
	param["appid"] = pcf.AppID
	param["body"] = p.Body
	param["mch_id"] = pcf.PayMchID
	param["nonce_str"] = nonceStr
	param["out_trade_no"] = p.OutTradeNo
	param["spbill_create_ip"] = p.CreateIP
	param["total_fee"] = p.TotalFee
	param["trade_type"] = p.TradeType
	param["openid"] = p.OpenIDÒ
	param["detail"] = p.Detail
	param["attach"] = p.Attach
	param["goods_tag"] = p.GoodsTag
	param["notify_url"] = pcf.PayNotifyURL
	// 签名类型
	if p.SignType != "" {
		param["sign_type"] = p.SignType
	}
	// 通知地址
	if p.NotifyURL != "" {
		param["notify_url"] = p.NotifyURL
	}

	bizKey := "&key=" + pcf.PayKey
	str := orderParam(param, bizKey)
	sign := util.MD5Sum(str)
	request := payRequest{
		AppID:          pcf.AppID,
		MchID:          pcf.PayMchID,
		NonceStr:       nonceStr,
		Sign:           sign,
		Body:           p.Body,
		OutTradeNo:     p.OutTradeNo,
		TotalFee:       p.TotalFee,
		SpbillCreateIP: p.CreateIP,
		NotifyURL:      pcf.PayNotifyURL,
		TradeType:      p.TradeType,
		OpenID:         p.OpenID,
	}
	rawRet, err := util.PostXML(payGateway, request)
	if err != nil {
		return
	}
	err = xml.Unmarshal(rawRet, &payOrder)
	if err != nil {
		return
	}
	if payOrder.ReturnCode == "SUCCESS" {
		// pay success
		if payOrder.ResultCode == "SUCCESS" {
			err = nil
			return
		}
		err = errors.New(payOrder.ErrCode + payOrder.ErrCodeDes)
		return
	}
	err = errors.New("[msg : xmlUnmarshalError] [rawReturn : " + string(rawRet) + "] [params : " + str + "] [sign : " + sign + "]")
	return
}

// PrePayID will request wechat merchant api and request for a pre payment order id
func (pcf *Pay) PrePayID(p *Params) (prePayID string, err error) {
	order, err := pcf.PrePayOrder(p)
	if err != nil {
		return
	}
	if order.PrePayID == "" {
		err = errors.New("empty prepayid")
	}
	prePayID = order.PrePayID
	return
}

// order params
func orderParam(source interface{}, bizKey string) (returnStr string) {
	switch v := source.(type) {
	case map[string]string:
		keys := make([]string, 0, len(v))
		for k := range v {
			if k == "sign" {
				continue
			}
			keys = append(keys, k)
		}
		sort.Strings(keys)
		var buf bytes.Buffer
		for _, k := range keys {
			if v[k] == "" {
				continue
			}
			if buf.Len() > 0 {
				buf.WriteByte('&')
			}
			buf.WriteString(k)
			buf.WriteByte('=')
			buf.WriteString(v[k])
		}
		buf.WriteString(bizKey)
		returnStr = buf.String()
	case map[string]interface{}:
		keys := make([]string, 0, len(v))
		for k := range v {
			if k == "sign" {
				continue
			}
			keys = append(keys, k)
		}
		sort.Strings(keys)
		var buf bytes.Buffer
		for _, k := range keys {
			if v[k] == "" {
				continue
			}
			if buf.Len() > 0 {
				buf.WriteByte('&')
			}
			buf.WriteString(k)
			buf.WriteByte('=')
			switch vv := v[k].(type) {
			case string:
				buf.WriteString(vv)
			case int:
				buf.WriteString(strconv.FormatInt(int64(vv), 10))
			default:
				panic("params type not supported")
			}
		}
		buf.WriteString(bizKey)
		returnStr = buf.String()
	}
	return
}
<commit_msg>支付 新增 BridgeConfig 方法，可获得 prepay ID，及js支付时所需要的参数<commit_after>package pay

import (
	"bytes"
	"crypto/hmac"
	"crypto/md5"
	"crypto/sha256"
	"encoding/hex"
	"encoding/xml"
	"errors"
	"hash"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/silenceper/wechat/context"
	"github.com/silenceper/wechat/util"
)

var payGateway = "https://api.mch.weixin.qq.com/pay/unifiedorder"

// Pay struct extends context
type Pay struct {
	*context.Context
}

// Params was NEEDED when request unifiedorder
// 传入的参数，用于生成 prepay_id 的必需参数
type Params struct {
	TotalFee   string
	CreateIP   string
	Body       string
	OutTradeNo string
	OpenID     string
	TradeType  string
	SignType   string
	Detail     string
	Attach     string
	GoodsTag   string
	NotifyURL  string
}

// Config 是传出用于 js sdk 用的参数
type Config struct {
	Timestamp string `json:"timestamp"`
	NonceStr  string `json:"nonceStr"`
	PrePayID  string `json:"prePayId"`
	SignType  string `json:"signType"`
	Package   string `json:"package"`
	PaySign   string `json:"paySign"`
}

// PreOrder 是 unifie order 接口的返回
type PreOrder struct {
	ReturnCode string `xml:"return_code"`
	ReturnMsg  string `xml:"return_msg"`
	AppID      string `xml:"appid,omitempty"`
	MchID      string `xml:"mch_id,omitempty"`
	NonceStr   string `xml:"nonce_str,omitempty"`
	Sign       string `xml:"sign,omitempty"`
	ResultCode string `xml:"result_code,omitempty"`
	TradeType  string `xml:"trade_type,omitempty"`
	PrePayID   string `xml:"prepay_id,omitempty"`
	CodeURL    string `xml:"code_url,omitempty"`
	ErrCode    string `xml:"err_code,omitempty"`
	ErrCodeDes string `xml:"err_code_des,omitempty"`
}

// payRequest 接口请求参数
type payRequest struct {
	AppID          string `xml:"appid"`
	MchID          string `xml:"mch_id"`
	DeviceInfo     string `xml:"device_info,omitempty"`
	NonceStr       string `xml:"nonce_str"`
	Sign           string `xml:"sign"`
	SignType       string `xml:"sign_type,omitempty"`
	Body           string `xml:"body"`
	Detail         string `xml:"detail,omitempty"`
	Attach         string `xml:"attach,omitempty"`      // 附加数据
	OutTradeNo     string `xml:"out_trade_no"`          // 商户订单号
	FeeType        string `xml:"fee_type,omitempty"`    // 标价币种
	TotalFee       string `xml:"total_fee"`             // 标价金额
	SpbillCreateIP string `xml:"spbill_create_ip"`      // 终端IP
	TimeStart      string `xml:"time_start,omitempty"`  // 交易起始时间
	TimeExpire     string `xml:"time_expire,omitempty"` // 交易结束时间
	GoodsTag       string `xml:"goods_tag,omitempty"`   // 订单优惠标记
	NotifyURL      string `xml:"notify_url"`            // 通知地址
	TradeType      string `xml:"trade_type"`            // 交易类型
	ProductID      string `xml:"product_id,omitempty"`  // 商品ID
	LimitPay       string `xml:"limit_pay,omitempty"`   //
	OpenID         string `xml:"openid,omitempty"`      // 用户标识
	SceneInfo      string `xml:"scene_info,omitempty"`  // 场景信息
}

// NewPay return an instance of Pay package
func NewPay(ctx *context.Context) *Pay {
	pay := Pay{Context: ctx}
	return &pay
}

// BridgeConfig get js bridge config
func (pcf *Pay) BridgeConfig(p *Params) (cfg Config, err error) {
	var (
		buffer    strings.Builder
		h         hash.Hash
		timestamp = strconv.FormatInt(time.Now().Unix(), 10)
	)
	order, err := pcf.PrePayOrder(p)
	if err != nil {
		return
	}
	buffer.WriteString("appId=")
	buffer.WriteString(order.AppID)
	buffer.WriteString("&nonceStr=")
	buffer.WriteString(order.NonceStr)
	buffer.WriteString("&package=")
	buffer.WriteString("prepay_id=" + order.PrePayID)
	buffer.WriteString("&signType=")
	buffer.WriteString(p.SignType)
	buffer.WriteString("&timeStamp=")
	buffer.WriteString(timestamp)
	buffer.WriteString("&key=")
	buffer.WriteString(pcf.PayKey)
	if p.SignType == "MD5" {
		h = md5.New()
	} else {
		h = hmac.New(sha256.New, []byte(pcf.PayKey))
	}
	h.Write([]byte(buffer.String()))
	// 签名
	cfg.PaySign = strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
	cfg.NonceStr = order.NonceStr
	cfg.Timestamp = timestamp
	cfg.PrePayID = order.PrePayID
	cfg.SignType = p.SignType
	cfg.Package = "prepay_id=" + order.PrePayID
	return
}

// PrePayOrder return data for invoke wechat payment
func (pcf *Pay) PrePayOrder(p *Params) (payOrder PreOrder, err error) {
	nonceStr := util.RandomStr(32)
	notifyURL := pcf.PayNotifyURL
	// 签名类型
	if p.SignType == "" {
		p.SignType = "MD5"
	}
	// 通知地址
	if p.NotifyURL != "" {
		notifyURL = p.NotifyURL
	}
	param := make(map[string]interface{})
	param["appid"] = pcf.AppID
	param["body"] = p.Body
	param["mch_id"] = pcf.PayMchID
	param["nonce_str"] = nonceStr
	param["out_trade_no"] = p.OutTradeNo
	param["spbill_create_ip"] = p.CreateIP
	param["total_fee"] = p.TotalFee
	param["trade_type"] = p.TradeType
	param["openid"] = p.OpenID
	param["detail"] = p.Detail
	param["attach"] = p.Attach
	param["goods_tag"] = p.GoodsTag
	param["notify_url"] = notifyURL

	bizKey := "&key=" + pcf.PayKey
	str := orderParam(param, bizKey)
	sign := util.MD5Sum(str)
	request := payRequest{
		AppID:          pcf.AppID,
		MchID:          pcf.PayMchID,
		NonceStr:       nonceStr,
		Sign:           sign,
		Body:           p.Body,
		OutTradeNo:     p.OutTradeNo,
		TotalFee:       p.TotalFee,
		SpbillCreateIP: p.CreateIP,
		NotifyURL:      notifyURL,
		TradeType:      p.TradeType,
		OpenID:         p.OpenID,
		SignType:       p.SignType,
		Detail:         p.Detail,
		Attach:         p.Attach,
		GoodsTag:       p.GoodsTag,
	}
	rawRet, err := util.PostXML(payGateway, request)
	if err != nil {
		return
	}
	err = xml.Unmarshal(rawRet, &payOrder)
	if err != nil {
		return
	}
	if payOrder.ReturnCode == "SUCCESS" {
		// pay success
		if payOrder.ResultCode == "SUCCESS" {
			err = nil
			return
		}
		err = errors.New(payOrder.ErrCode + payOrder.ErrCodeDes)
		return
	}
	err = errors.New("[msg : xmlUnmarshalError] [rawReturn : " + string(rawRet) + "] [params : " + str + "] [sign : " + sign + "]")
	return
}

// PrePayID will request wechat merchant api and request for a pre payment order id
func (pcf *Pay) PrePayID(p *Params) (prePayID string, err error) {
	order, err := pcf.PrePayOrder(p)
	if err != nil {
		return
	}
	if order.PrePayID == "" {
		err = errors.New("empty prepayid")
	}
	prePayID = order.PrePayID
	return
}

// order params
func orderParam(source interface{}, bizKey string) (returnStr string) {
	switch v := source.(type) {
	case map[string]string:
		keys := make([]string, 0, len(v))
		for k := range v {
			if k == "sign" {
				continue
			}
			keys = append(keys, k)
		}
		sort.Strings(keys)
		var buf bytes.Buffer
		for _, k := range keys {
			if v[k] == "" {
				continue
			}
			if buf.Len() > 0 {
				buf.WriteByte('&')
			}
			buf.WriteString(k)
			buf.WriteByte('=')
			buf.WriteString(v[k])
		}
		buf.WriteString(bizKey)
		returnStr = buf.String()
	case map[string]interface{}:
		keys := make([]string, 0, len(v))
		for k := range v {
			if k == "sign" {
				continue
			}
			keys = append(keys, k)
		}
		sort.Strings(keys)
		var buf bytes.Buffer
		for _, k := range keys {
			if v[k] == "" {
				continue
			}
			if buf.Len() > 0 {
				buf.WriteByte('&')
			}
			buf.WriteString(k)
			buf.WriteByte('=')
			switch vv := v[k].(type) {
			case string:
				buf.WriteString(vv)
			case int:
				buf.WriteString(strconv.FormatInt(int64(vv), 10))
			default:
				panic("params type not supported")
			}
		}
		buf.WriteString(bizKey)
		returnStr = buf.String()
	}
	return
}
<|endoftext|>


<commit_before>package adyen

/* One-click functionality gives the shopper the option to store their payment details with the merchant, within the Adyen environment. In this type of transaction, the shopper needs to enter the CVC code for the transaction to get through.
Same than for ONECLICK except than the shopper doesn't need to enter the CVC */
const (
	ONECLICK                                 = "ONECLICK"
	RECURRING                                = "RECURRING"
	SHOPPER_INTERACTION_CONTAUTH             = "ContAuth"
	SELECT_RECURRING_DETAIL_REFERENCE_LATEST = "LATEST"
)

// AuthoriseEncrypted structure for Authorisation request (with encrypted card information)
type AuthoriseEncrypted struct {
	AdditionalData  *AdditionalData `json:"additionalData,omitempty"`
	Amount          *Amount         `json:"amount"`
	Reference       string          `json:"reference"`
	MerchantAccount string          `json:"merchantAccount"`
	// Mandatory for recurring payment
	ShopperReference                 string     `json:"shopperReference,omitempty"`
	Recurring                        *Recurring `json:"recurring,omitempty"`
	ShopperInteraction               string     `json:"shopperInteraction,omitempty"`
	SelectedRecurringDetailReference string     `json:"selectedRecurringDetailReference,omitempty"`
	// Required for a 3DS process
	BrowserInfo *BrowserInfo `json:"browserInfo,omitempty"`
}

// Authorise structure for Authorisation request (card is not encrypted)
type Authorise struct {
	Card            *Card   `json:"card,omitempty"`
	Amount          *Amount `json:"amount"`
	Reference       string  `json:"reference"`
	MerchantAccount string  `json:"merchantAccount"`
	// Mandatory for recurring payment
	ShopperReference                 string     `json:"shopperReference,omitempty"`
	Recurring                        *Recurring `json:"recurring,omitempty"`
	ShopperInteraction               string     `json:"shopperInteraction,omitempty"`
	SelectedRecurringDetailReference string     `json:"selectedRecurringDetailReference,omitempty"`
	// Required for a 3DS process
	BrowserInfo *BrowserInfo `json:"browserInfo,omitempty"`
}

// AuthoriseResponse is a response structure for Adyen
type AuthoriseResponse struct {
	PspReference  string `json:"pspReference"`
	ResultCode    string `json:"resultCode"`
	AuthCode      string `json:"authCode"`
	RefusalReason string `json:"refusalReason"`
	IssuerURL     string `json:"issuerUrl"`
	MD            string `json:"md"`
	PaRequest     string `json:"paRequest"`
}

// AdditionalData stores encrypted information about customer's credit card
type AdditionalData struct {
	Content string `json:"card.encrypted.json"`
}

// BrowserInfo hold information on the user browser
type BrowserInfo struct {
	AcceptHeader string `json:"acceptHeader"`
	UserAgent    string `json:"userAgent"`
}

// Recurring hold the behavior for a future payment : could be ONECLICK or RECURRING
type Recurring struct {
	Contract string `json:"contract"`
}
<commit_msg>Rename const from UpperCase to CamelCaps<commit_after>package adyen

/* One-click functionality gives the shopper the option to store their payment details with the merchant, within the Adyen environment. In this type of transaction, the shopper needs to enter the CVC code for the transaction to get through.
Same than for ONECLICK except than the shopper doesn't need to enter the CVC */
const (
	RecurringPaymentOneClick              = "ONECLICK"
	RecurringPaymentRecurring             = "RECURRING"
	ShopperInteractionContAuth            = "ContAuth"
	SelectRecurringDetailReferenceLatests = "LATEST"
)

// AuthoriseEncrypted structure for Authorisation request (with encrypted card information)
type AuthoriseEncrypted struct {
	AdditionalData  *AdditionalData `json:"additionalData,omitempty"`
	Amount          *Amount         `json:"amount"`
	Reference       string          `json:"reference"`
	MerchantAccount string          `json:"merchantAccount"`
	// Mandatory for recurring payment
	ShopperReference                 string     `json:"shopperReference,omitempty"`
	Recurring                        *Recurring `json:"recurring,omitempty"`
	ShopperInteraction               string     `json:"shopperInteraction,omitempty"`
	SelectedRecurringDetailReference string     `json:"selectedRecurringDetailReference,omitempty"`
	// Required for a 3DS process
	BrowserInfo *BrowserInfo `json:"browserInfo,omitempty"`
}

// Authorise structure for Authorisation request (card is not encrypted)
type Authorise struct {
	Card            *Card   `json:"card,omitempty"`
	Amount          *Amount `json:"amount"`
	Reference       string  `json:"reference"`
	MerchantAccount string  `json:"merchantAccount"`
	// Mandatory for recurring payment
	ShopperReference                 string     `json:"shopperReference,omitempty"`
	Recurring                        *Recurring `json:"recurring,omitempty"`
	ShopperInteraction               string     `json:"shopperInteraction,omitempty"`
	SelectedRecurringDetailReference string     `json:"selectedRecurringDetailReference,omitempty"`
	// Required for a 3DS process
	BrowserInfo *BrowserInfo `json:"browserInfo,omitempty"`
}

// AuthoriseResponse is a response structure for Adyen
type AuthoriseResponse struct {
	PspReference  string `json:"pspReference"`
	ResultCode    string `json:"resultCode"`
	AuthCode      string `json:"authCode"`
	RefusalReason string `json:"refusalReason"`
	IssuerURL     string `json:"issuerUrl"`
	MD            string `json:"md"`
	PaRequest     string `json:"paRequest"`
}

// AdditionalData stores encrypted information about customer's credit card
type AdditionalData struct {
	Content string `json:"card.encrypted.json"`
}

// BrowserInfo hold information on the user browser
type BrowserInfo struct {
	AcceptHeader string `json:"acceptHeader"`
	UserAgent    string `json:"userAgent"`
}

// Recurring hold the behavior for a future payment : could be ONECLICK or RECURRING
type Recurring struct {
	Contract string `json:"contract"`
}
<|endoftext|>


<commit_before>package action

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

	"github.com/errata-ai/vale/check"
	"github.com/errata-ai/vale/core"
	"github.com/errata-ai/vale/lint"
	"github.com/errata-ai/vale/ui"
	"github.com/jdkato/prose/v2"
)

// TagSentence assigns part-of-speech tags to the given sentence.
func TagSentence(config *core.Config, text string) error {
	doc, err := prose.NewDocument(text, prose.WithExtraction(false))
	if core.CheckError(err, true) {
		observed := []string{}
		for _, tok := range doc.Tokens() {
			observed = append(observed, (tok.Text + "/" + tok.Tag))
		}
		fmt.Println(strings.Join(observed, " "))
	}
	return nil
}

// ListConfig prints Vale's active configuration.
func ListConfig(config *core.Config) error {
	fmt.Println(core.DumpConfig(config))
	return nil
}

// GetTemplate prints tamplate for the given extension point.
func GetTemplate(name string) error {
	template := check.GetTemplate(name)
	if template != "" {
		fmt.Println(template)
	} else {
		fmt.Printf(
			"'%s' not in %v!\n", name, check.GetExtenionPoints())
	}
	return nil
}

// CompileRule returns a compiled rule.
func CompileRule(config *core.Config, path string) error {
	if path == "" {
		fmt.Println("invalid rule path")
	} else {
		fName := filepath.Base(path)

		mgr := check.Manager{AllChecks: make(map[string]check.Check), Config: config}
		if core.CheckError(mgr.Compile(fName, path), true) {
			for _, v := range mgr.AllChecks {
				fmt.Print(v.Pattern)
			}
		}
	}
	return nil
}

// TestRule returns the linting results for a single rule
func TestRule(args []string) error {
	if len(args) == 2 && core.FileExists(args[0]) && core.FileExists(args[1]) {
		rule, _ := ioutil.ReadFile(args[0])
		text, _ := ioutil.ReadFile(args[1])

		// Create a pre-filled configuration:
		config := core.NewConfig()
		config.MinAlertLevel = 0
		config.GBaseStyles = append(config.GBaseStyles, "Test")

		// Create our check manager:
		mgr := check.Manager{
			AllChecks: make(map[string]check.Check),
			Config:    config}

		mgr.AddCheck(rule, "Test.Rule")
		linter := lint.Linter{CheckManager: &mgr}

		linted, err := linter.LintString(string(text))
		_ = ui.PrintJSONAlerts(linted)

		return err
	} else if len(args) != 2 {
		fmt.Println("missing argument")
	}

	fmt.Println("invalid arguments")
	return nil
}
<commit_msg>fix: ensure `Config.Scopes` is initialized in actions<commit_after>package action

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

	"github.com/errata-ai/vale/check"
	"github.com/errata-ai/vale/core"
	"github.com/errata-ai/vale/lint"
	"github.com/errata-ai/vale/ui"
	"github.com/jdkato/prose/v2"
)

// TagSentence assigns part-of-speech tags to the given sentence.
func TagSentence(config *core.Config, text string) error {
	doc, err := prose.NewDocument(text, prose.WithExtraction(false))
	if core.CheckError(err, true) {
		observed := []string{}
		for _, tok := range doc.Tokens() {
			observed = append(observed, (tok.Text + "/" + tok.Tag))
		}
		fmt.Println(strings.Join(observed, " "))
	}
	return nil
}

// ListConfig prints Vale's active configuration.
func ListConfig(config *core.Config) error {
	fmt.Println(core.DumpConfig(config))
	return nil
}

// GetTemplate prints tamplate for the given extension point.
func GetTemplate(name string) error {
	template := check.GetTemplate(name)
	if template != "" {
		fmt.Println(template)
	} else {
		fmt.Printf(
			"'%s' not in %v!\n", name, check.GetExtenionPoints())
	}
	return nil
}

// CompileRule returns a compiled rule.
func CompileRule(config *core.Config, path string) error {
	if path == "" {
		fmt.Println("invalid rule path")
	} else {
		fName := filepath.Base(path)

		mgr := check.Manager{
			AllChecks: make(map[string]check.Check),
			Config:    config,
			Scopes:    make(map[string]struct{}),
		}

		if core.CheckError(mgr.Compile(fName, path), true) {
			for _, v := range mgr.AllChecks {
				fmt.Print(v.Pattern)
			}
		}
	}
	return nil
}

// TestRule returns the linting results for a single rule
func TestRule(args []string) error {
	if len(args) == 2 && core.FileExists(args[0]) && core.FileExists(args[1]) {
		rule, _ := ioutil.ReadFile(args[0])

		// Create a pre-filled configuration:
		config := core.NewConfig()
		config.MinAlertLevel = 0
		config.GBaseStyles = append(config.GBaseStyles, "Test")
		config.InExt = ".txt" // default value

		// Create our check manager:
		mgr := check.Manager{
			AllChecks: make(map[string]check.Check),
			Config:    config,
			Scopes:    make(map[string]struct{}),
		}

		mgr.AddCheck(rule, "Test.Rule")
		linter := lint.Linter{CheckManager: &mgr}

		linted, err := linter.Lint([]string{args[1]}, "*")
		_ = ui.PrintJSONAlerts(linted)

		return err
	} else if len(args) != 2 {
		fmt.Println("missing argument")
	}

	fmt.Println("invalid arguments")
	return nil
}
<|endoftext|>


<commit_before>package models_test

/* NOTE: main_test.go contains the TestMain, setup, and teardown functions for this suite. */

import (
	"fmt"
	"github.com/APTrust/easy-store/db/models"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"testing"
)

func TestGetId(t *testing.T) {
	bag := FakeBag()
	assert.Equal(t, bag.Id, bag.GetId())
}

func TestTableName(t *testing.T) {
	bag := FakeBag()
	assert.Equal(t, "bags", bag.TableName())
}

func TestValidate(t *testing.T) {
	bag := FakeBag()
	assert.True(t, bag.Validate())
	assert.NotNil(t, bag.Errors())
	assert.Empty(t, bag.Errors())
}

func TestErrors(t *testing.T) {
	bag := FakeBag()
	assert.NotNil(t, bag.Errors())
	assert.Empty(t, bag.Errors())
}

func TestBagSave(t *testing.T) {
	// Save as insert
	bag := FakeBag()
	bag.Id = 0
	ok := bag.Save(false)
	assert.True(t, ok)
	assert.NotEqual(t, 0, bag.Id)
	assert.Empty(t, bag.Errors())

	// Save as update
	id := bag.Id
	bag.Size = bag.Size + 20
	ok = bag.Save(false)
	assert.True(t, ok)
	assert.Equal(t, id, bag.Id)
	assert.Empty(t, bag.Errors())
}

func TestGetBag(t *testing.T) {
	// Save first
	bag := FakeBag()
	bag.Id = 0
	ok := bag.Save(false)
	assert.True(t, ok)
	assert.NotEqual(t, 0, bag.Id)

	// Now get
	retrievedBag, err := models.GetBag(bag.Id)
	require.Nil(t, err)
	assert.Equal(t, bag.Id, retrievedBag.Id)
	assert.Equal(t, bag.Name, retrievedBag.Name)
}

func TestGetBags(t *testing.T) {
	// Delete bags created by other tests
	_, err := models.ExecCommand("delete from bags", nil)
	require.Nil(t, err)

	// Save some first
	for i := 0; i < 10; i++ {
		bag := FakeBag()
		bag.Id = 0
		if i%2 == 0 {
			bag.Name = fmt.Sprintf("Even %d", i)
		} else {
			bag.Name = fmt.Sprintf("Odd %d", i)
		}
		if i%3 == 0 {
			bag.MetadataURL = ""
		}
		ok := bag.Save(false)
		assert.True(t, ok)
		assert.NotEqual(t, 0, bag.Id)
	}

	// Now select
	// Bags 3 and 9 have Odd name and empty MetadataURL
	where := "name like ? and metadata_url = ?"
	values := []interface{}{
		"Odd%",
		"",
	}
	bags, err := models.GetBags(where, values)
	require.Nil(t, err)
	require.NotNil(t, bags)
	assert.Equal(t, 2, len(bags))

	// Should get ten bags
	where = ""
	values = []interface{}{}
	bags, err = models.GetBags(where, values)
	require.Nil(t, err)
	require.NotNil(t, bags)
	assert.Equal(t, 10, len(bags))

	// Should also get ten bags
	where = "name like 'Even %' or name like 'Odd%'"
	values = make([]interface{}, 0)
	bags, err = models.GetBags(where, values)
	require.Nil(t, err)
	require.NotNil(t, bags)
	assert.Equal(t, 10, len(bags))

	// Should get bags
	where = "name like :name"
	values = []interface{}{
		"Even%",
	}
	bags, err = models.GetBags(where, values)
	require.Nil(t, err)
	require.NotNil(t, bags)
	assert.Equal(t, 5, len(bags))
}
<commit_msg>Make sure Save assigns properties correctly<commit_after>package models_test

/* NOTE: main_test.go contains the TestMain, setup, and teardown functions for this suite. */

import (
	"fmt"
	"github.com/APTrust/easy-store/db/models"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"testing"
)

func TestGetId(t *testing.T) {
	bag := FakeBag()
	assert.Equal(t, bag.Id, bag.GetId())
}

func TestTableName(t *testing.T) {
	bag := FakeBag()
	assert.Equal(t, "bags", bag.TableName())
}

func TestValidate(t *testing.T) {
	bag := FakeBag()
	assert.True(t, bag.Validate())
	assert.NotNil(t, bag.Errors())
	assert.Empty(t, bag.Errors())
}

func TestErrors(t *testing.T) {
	bag := FakeBag()
	assert.NotNil(t, bag.Errors())
	assert.Empty(t, bag.Errors())
}

func TestBagSave(t *testing.T) {
	// Save as insert
	bag := FakeBag()
	bag.Id = 0
	ok := bag.Save(false)
	assert.True(t, ok)
	assert.NotEqual(t, 0, bag.Id)
	assert.Empty(t, bag.Errors())

	// Save as update
	id := bag.Id
	bag.Size = bag.Size + 20
	ok = bag.Save(false)
	assert.True(t, ok)
	assert.Equal(t, id, bag.Id)
	assert.Empty(t, bag.Errors())
}

func TestGetBag(t *testing.T) {
	// Save first
	bag := FakeBag()
	bag.Id = 0
	ok := bag.Save(false)
	assert.True(t, ok)
	assert.NotEqual(t, 0, bag.Id)

	// Now get
	retrievedBag, err := models.GetBag(bag.Id)
	require.Nil(t, err)
	assert.Equal(t, bag.Id, retrievedBag.Id)
	assert.Equal(t, bag.Name, retrievedBag.Name)
	assert.Equal(t, bag.Size, retrievedBag.Size)
	assert.Equal(t, bag.StorageURL, retrievedBag.StorageURL)
	assert.Equal(t, bag.MetadataURL, retrievedBag.MetadataURL)
	assert.Equal(t, bag.StorageRegistryIdentifier, retrievedBag.StorageRegistryIdentifier)
	assert.Equal(t, bag.StoredAt, retrievedBag.StoredAt)
	assert.Equal(t, bag.CreatedAt, retrievedBag.CreatedAt)
	assert.Equal(t, bag.UpdatedAt, retrievedBag.UpdatedAt)
	assert.Empty(t, bag.Errors())
}

func TestGetBags(t *testing.T) {
	// Delete bags created by other tests
	_, err := models.ExecCommand("delete from bags", nil)
	require.Nil(t, err)

	// Save some first
	for i := 0; i < 10; i++ {
		bag := FakeBag()
		bag.Id = 0
		if i%2 == 0 {
			bag.Name = fmt.Sprintf("Even %d", i)
		} else {
			bag.Name = fmt.Sprintf("Odd %d", i)
		}
		if i%3 == 0 {
			bag.MetadataURL = ""
		}
		ok := bag.Save(false)
		assert.True(t, ok)
		assert.NotEqual(t, 0, bag.Id)
	}

	// Now select
	// Bags 3 and 9 have Odd name and empty MetadataURL
	where := "name like ? and metadata_url = ?"
	values := []interface{}{
		"Odd%",
		"",
	}
	bags, err := models.GetBags(where, values)
	require.Nil(t, err)
	require.NotNil(t, bags)
	assert.Equal(t, 2, len(bags))

	// Should get ten bags
	where = ""
	values = []interface{}{}
	bags, err = models.GetBags(where, values)
	require.Nil(t, err)
	require.NotNil(t, bags)
	assert.Equal(t, 10, len(bags))

	// Should also get ten bags
	where = "name like 'Even %' or name like 'Odd%'"
	values = make([]interface{}, 0)
	bags, err = models.GetBags(where, values)
	require.Nil(t, err)
	require.NotNil(t, bags)
	assert.Equal(t, 10, len(bags))

	// Should get bags
	where = "name like :name"
	values = []interface{}{
		"Even%",
	}
	bags, err = models.GetBags(where, values)
	require.Nil(t, err)
	require.NotNil(t, bags)
	assert.Equal(t, 5, len(bags))
}
<|endoftext|>


<commit_before>package ofutils

import (
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"math/rand"
	"net/smtp"
	"os"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/astaxie/beego/orm"
	"github.com/axgle/mahonia"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func RandString(n int) string {
	b := make([]rune, n)
	for i := range b {
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
	}
	return string(b)
}

func MD5(text string) string {
	hasher := md5.New()
	hasher.Write([]byte(text))
	return hex.EncodeToString(hasher.Sum(nil))
}

func ToString(str interface{}) string {
	if str == nil {
		return ""
	}
	return fmt.Sprintf("%v", str)
}

func ToInt(val interface{}) int {
	if val == nil {
		return 0
	}
	s, ok := val.(string)
	if ok {
		i, err := strconv.Atoi(s)
		if err != nil {
			return 0
		}
		return i
	}
	i, ok := val.(int)
	if ok {
		return i
	} else {
		return 0
	}
}

func GetWeekFirstDay() string {
	week := time.Now().Weekday().String()
	var day time.Duration
	switch week {
	case "Sunday":
		day = 6
		break
	case "Monday":
		day = 0
		break
	case "Tuesday":
		day = 1
		break
	case "Wednesday":
		day = 2
		break
	case "Thursday":
		day = 3
		break
	case "Friday":
		day = 4
		break
	case "Saturday":
		day = 5
		break
	}
	date := time.Now().Add(-day * 24 * time.Hour)
	return date.Format("2006-01-02")
}

type ByKey struct {
	Key  string
	List []orm.Params
}

func (a ByKey) Len() int {
	return len(a.List)
}
func (a ByKey) Swap(i, j int) {
	a.List[i], a.List[j] = a.List[j], a.List[i]
}
func (a ByKey) Less(i, j int) bool {
	return ToInt(a.List[i][a.Key]) > ToInt(a.List[j][a.Key])
}

func Sort(list []orm.Params, key string) []orm.Params {
	byKey := ByKey{List: list, Key: key}
	sort.Sort(byKey)
	return byKey.List
}

func SubString(str string, begin, length int) (substr string) {
	// 将字符串的转换成[]rune
	rs := []rune(str)
	lth := len(rs)

	// 简单的越界判断
	if begin < 0 {
		begin = 0
	}
	if begin >= lth {
		begin = lth
	}
	end := begin + length
	if end > lth {
		end = lth
	}
	// 返回子串
	return string(rs[begin:end])
}

func ToFloat(str interface{}) float64 {
	if str == nil {
		return 0
	}
	tf, err := strconv.ParseFloat(ToString(str), 64)
	if err != nil {
		return 0
	}
	return tf
}
func ToJson(datas interface{}) string {
	jsonString, _ := json.Marshal(datas)
	return string(jsonString)
}
func GetEncryptPhone(phone interface{}) string {
	temp := ToString(phone)
	if len(temp) == 11 {
		start := SubString(temp, 0, 3)
		end := SubString(temp, 7, 11)
		temp = start + "****" + end
	}
	return temp
}
func Exist(filename string) bool {
	_, err := os.Stat(filename)
	return err == nil || os.IsExist(err)
}
func SendMail(user, password, host, to, subject, body, mailtype string) error {
	hp := strings.Split(host, ":")
	auth := smtp.PlainAuth("", user, password, hp[0])
	var content_type string
	if mailtype == "html" {
		content_type = "Content-Type: text/" + mailtype + "; charset=UTF-8"
	} else {
		content_type = "Content-Type: text/plain" + "; charset=UTF-8"
	}

	msg := []byte("To: " + to + "\r\nFrom: " + user + "<" + user + ">\r\nSubject: " + subject + "\r\n" + content_type + "\r\n\r\n" + body)
	send_to := strings.Split(to, ";")
	err := smtp.SendMail(host, auth, user, send_to, msg)
	return err
}
func ZeroBefore(i int) string {
	if i < 10 {
		return "0" + ToString(i)
	}
	return ToString(i)
}
func GetTimeStamp() string {
	return time.Now().Format("20060102150405")
}
func Utf8ToGBK(text string) string {
	enc := mahonia.NewEncoder("gbk")
	return enc.ConvertString(text)
}
func Copy(dst, src string) error {
	in, err := os.Open(src)
	if err != nil {
		return err
	}
	defer in.Close()
	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer out.Close()
	_, err = io.Copy(out, in)
	cerr := out.Close()
	if err != nil {
		return err
	}
	return cerr
}
<commit_msg>update<commit_after>package ofutils

import (
	"bufio"
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"math/rand"
	"net/smtp"
	"os"
	"sort"
	"strconv"
	"strings"
	"time"

	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"

	"github.com/astaxie/beego/orm"
	"github.com/axgle/mahonia"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func RandString(n int) string {
	b := make([]rune, n)
	for i := range b {
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
	}
	return string(b)
}

func MD5(text string) string {
	hasher := md5.New()
	hasher.Write([]byte(text))
	return hex.EncodeToString(hasher.Sum(nil))
}

func ToString(str interface{}) string {
	if str == nil {
		return ""
	}
	return fmt.Sprintf("%v", str)
}

func ToInt(val interface{}) int {
	if val == nil {
		return 0
	}
	s, ok := val.(string)
	if ok {
		i, err := strconv.Atoi(s)
		if err != nil {
			return 0
		}
		return i
	}
	i, ok := val.(int)
	if ok {
		return i
	} else {
		return 0
	}
}

func GetWeekFirstDay() string {
	week := time.Now().Weekday().String()
	var day time.Duration
	switch week {
	case "Sunday":
		day = 6
		break
	case "Monday":
		day = 0
		break
	case "Tuesday":
		day = 1
		break
	case "Wednesday":
		day = 2
		break
	case "Thursday":
		day = 3
		break
	case "Friday":
		day = 4
		break
	case "Saturday":
		day = 5
		break
	}
	date := time.Now().Add(-day * 24 * time.Hour)
	return date.Format("2006-01-02")
}

type ByKey struct {
	Key  string
	List []orm.Params
}

func (a ByKey) Len() int {
	return len(a.List)
}
func (a ByKey) Swap(i, j int) {
	a.List[i], a.List[j] = a.List[j], a.List[i]
}
func (a ByKey) Less(i, j int) bool {
	return ToInt(a.List[i][a.Key]) > ToInt(a.List[j][a.Key])
}

func Sort(list []orm.Params, key string) []orm.Params {
	byKey := ByKey{List: list, Key: key}
	sort.Sort(byKey)
	return byKey.List
}

func SubString(str string, begin, length int) (substr string) {
	// 将字符串的转换成[]rune
	rs := []rune(str)
	lth := len(rs)

	// 简单的越界判断
	if begin < 0 {
		begin = 0
	}
	if begin >= lth {
		begin = lth
	}
	end := begin + length
	if end > lth {
		end = lth
	}
	// 返回子串
	return string(rs[begin:end])
}

func ToFloat(str interface{}) float64 {
	if str == nil {
		return 0
	}
	tf, err := strconv.ParseFloat(ToString(str), 64)
	if err != nil {
		return 0
	}
	return tf
}
func ToJson(datas interface{}) string {
	jsonString, _ := json.Marshal(datas)
	return string(jsonString)
}
func GetEncryptPhone(phone interface{}) string {
	temp := ToString(phone)
	if len(temp) == 11 {
		start := SubString(temp, 0, 3)
		end := SubString(temp, 7, 11)
		temp = start + "****" + end
	}
	return temp
}
func Exist(filename string) bool {
	_, err := os.Stat(filename)
	return err == nil || os.IsExist(err)
}
func SendMail(user, password, host, to, subject, body, mailtype string) error {
	hp := strings.Split(host, ":")
	auth := smtp.PlainAuth("", user, password, hp[0])
	var content_type string
	if mailtype == "html" {
		content_type = "Content-Type: text/" + mailtype + "; charset=UTF-8"
	} else {
		content_type = "Content-Type: text/plain" + "; charset=UTF-8"
	}

	msg := []byte("To: " + to + "\r\nFrom: " + user + "<" + user + ">\r\nSubject: " + subject + "\r\n" + content_type + "\r\n\r\n" + body)
	send_to := strings.Split(to, ";")
	err := smtp.SendMail(host, auth, user, send_to, msg)
	return err
}
func ZeroBefore(i int) string {
	if i < 10 {
		return "0" + ToString(i)
	}
	return ToString(i)
}
func GetTimeStamp() string {
	return time.Now().Format("20060102150405")
}
func Utf8ToGBK(text string) string {
	enc := mahonia.NewEncoder("gbk")
	return enc.ConvertString(text)
}
func GBKFileToUtf8(filePath string) string {
	// Read UTF-8 from a GBK encoded file.
	f, err := os.Open(filePath)
	if err != nil {
		log.Fatal(err)
	}
	r := transform.NewReader(f, simplifiedchinese.GBK.NewDecoder())

	// Read converted UTF-8 from `r` as needed.
	// As an example we'll read line-by-line showing what was read:
	sc := bufio.NewScanner(r)
	result := ""
	for sc.Scan() {
		result += string(sc.Bytes()) + "\n"
	}
	return result
}
func TrimSuffix(s, suffix string) string {
	if strings.HasSuffix(s, suffix) {
		s = s[:len(s)-len(suffix)]
	}
	return s
}
func TrimPrefix(s, suffix string) string {
	if strings.HasPrefix(s, suffix) {
		s = s[len(suffix):]
	}
	return s
}
func Copy(dst, src string) error {
	in, err := os.Open(src)
	if err != nil {
		return err
	}
	defer in.Close()
	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer out.Close()
	_, err = io.Copy(out, in)
	cerr := out.Close()
	if err != nil {
		return err
	}
	return cerr
}
<|endoftext|>