<commit_before>package main

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"math"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"syscall"
	"time"
)

type updateJob struct {
	progress   *Progress
	onProgress chan *Progress
}

func (u *updateJob) start() {

	u.progress = &Progress{
		Running:   true,
		startTime: time.Now(),
	}

	u.updateProgress(0, "Looking for updates", "")

	u.cleanup()

	err := u.setReadWrite(true)
	if err != nil {
		u.updateProgress(0, "Failed to enable disk writing", fmt.Sprintf("Error: %s", err))
		return
	}
	defer u.setReadWrite(false)

	log.Infof("Updating from repositories")

	err = u.updateCache(45, 0, 25)
	if err != nil {
		u.updateProgress(0, "Failed", fmt.Sprintf("Error: %s", err))
		return
	}

	u.updateProgress(27, "Processing available updates", "")

	updates, err := u.getAvailableUpdates()

	if err != nil {
		u.updateProgress(0, "Failed", fmt.Sprintf("Error: %s", err))
		return
	}

	updates = append(updates, AvailableUpdate{
		Name: "ninjasphere", // Always force it
	}, AvailableUpdate{
		Name: "ninjasphere-drivers", // Always force it
	})

	// Check to see if our "get out of jail free" card has been played
	for _, update := range updates {
		if update.Name == "sphere-idspispopd" {
			err = u.installUpdates([]AvailableUpdate{update})

			if err != nil {
				u.updateProgress(0, "Failed running pre-install script", fmt.Sprintf("Error: %s", err))
				return
			}

			updates, err = u.getAvailableUpdates()

			if err != nil {
				u.updateProgress(0, "Failed", fmt.Sprintf("Error: %s", err))
				return
			}
		}
	}

	u.autoRemove()

	log.Infof("%d packages to update: %v", len(updates), updates)

	if len(updates) > 0 {

		u.updateProgress(30, "Installing updates", "")

		err = u.installUpdates(updates)

		if err != nil {
			u.updateProgress(0, "Failed", fmt.Sprintf("Error: %s", err))
			return
		}
	}

	u.updateProgress(100, "Finished", "")
}

func (u *updateJob) updateProgress(percent float64, description, err string) {

	if percent == 100 || err != "" {
		u.progress.Running = false
	}

	if percent > u.progress.Percent {
		u.progress.Percent = percent
	}

	if err != "" {
		u.progress.Error = &err
	}

	if description != "" {
		u.progress.Description = description
	}

	u.onProgress <- u.progress
}

func (u *updateJob) setReadWrite(writing bool) error {
	if runtime.GOOS != "linux" {
		return nil
	}

	mode := "ro"
	if writing {
		mode = "rw"
	}

	cmd := exec.Command("mount", "-o", "remount,"+mode, "/")

	output, err := cmd.Output()
	log.Infof("Output from mount: %s", output)

	return err
}

func (u *updateJob) updateCache(expectedLines float64, startPercent float64, totalPercent float64) error {

	if runtime.GOOS != "linux" {
		return nil
	}

	updateLines := 0.0

	cmd := exec.Command("apt-get", "update", "-q")

	reader, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}

	bufReader := bufio.NewReader(reader)

	err = cmd.Start()

	if err != nil {
		return err
	}

	for {
		_, _, err := bufReader.ReadLine()

		if err != nil {
			//log.Infof("ERR:%s", err)
			break
		}

		updateLines++
		//cleaned := invalidChar.ReplaceAll([]byte(x[0:n]), []byte(""))

		u.updateProgress(startPercent+math.Min(totalPercent, (updateLines/expectedLines)*totalPercent), "", "")
		//	log.Infof("GOT: |%s| %t", line, isPrefix)
	}

	if err := cmd.Wait(); err != nil {
		if exiterr, ok := err.(*exec.ExitError); ok {
			// The program has exited with an exit code != 0
			// There is no plattform independent way to retrieve
			// the exit code, but the following will work on Unix
			if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
				log.Infof("updateCache Bad Exit Status: %d", status.ExitStatus())
				return fmt.Errorf("Failed to update cache. Code: %d", status.ExitStatus())
			}
		} else {
			log.Infof("Update cache : cmd.Wait: %v", err)
		}
	}

	return nil
}

func (u *updateJob) cleanup() {
	cmd := exec.Command("dpkg", "--configure", "-a")

	output, _ := cmd.Output()

	log.Infof("Output from dpkg: %s", output)

}

func (u *updateJob) autoRemove() {
	cmd := exec.Command("apt-get", "auto-remove")

	output, _ := cmd.Output()

	log.Infof("Output from apt-get autoremove: %s", output)
}

func (u *updateJob) getAvailableUpdates() ([]AvailableUpdate, error) {
	var err error
	var available []byte

	ioutil.WriteFile("./available-updates.sh", []byte(`#!/bin/bash
	  apt-get -s dist-upgrade| awk -F'[][() ]+' '/^Inst/{printf "%s\t%s\t%s\n", $2,$3,$4}'`), os.FileMode(755))

	cmd := exec.Command("./available-updates.sh")

	if runtime.GOOS == "linux" {
		available, err = cmd.Output()
	} else {
		available, err = ioutil.ReadFile("./updates.txt")
	}

	if err != nil {
		return nil, fmt.Errorf("Failed to get updatable packages. Error: %s", err)
	}

	var updates []AvailableUpdate

	for _, line := range strings.Split(string(available), "\n") {
		s := strings.Split(line, "\t")
		if len(s) == 3 && strings.Contains(line, "spheramid") && !strings.Contains(line, "sphere-updates") && !strings.Contains(line, "sphere-setup-assistant") {
			updates = append(updates, AvailableUpdate{s[0], s[1], s[2]})
		}
	}

	if runtime.GOOS == "linux" {
		if err := cmd.Wait(); err != nil {
			if exiterr, ok := err.(*exec.ExitError); ok {
				// The program has exited with an exit code != 0
				// There is no plattform independent way to retrieve
				// the exit code, but the following will work on Unix
				if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
					log.Infof("Bad Exit Status: %d", status.ExitStatus())
					return nil, fmt.Errorf("Failed to get updatable packages. Code: %d", status.ExitStatus())
				}
			} else {
				log.Infof("Get updatable : cmd.Wait: %v", err)
			}
		}
	}

	return updates, nil
}

func (u *updateJob) installUpdates(updates []AvailableUpdate) error {

	var cmd *exec.Cmd
	if runtime.GOOS == "linux" {
		args := []string{"install", "-yy", "-q"}
		for _, update := range updates {
			args = append(args, update.Name)
		}

		log.Infof("Running update command : apt-get %s", strings.Join(args, " "))

		cmd = exec.Command("apt-get", args...)
		cmd.Stderr = os.Stderr
	} else {
		cmd = exec.Command("cat", "./upgrade.txt")
	}

	os.Setenv("DEBIAN_FRONTEND", "noninteractive")

	reader, err := cmd.StdoutPipe()

	bufReader := bufio.NewReader(reader)

	err = cmd.Start()

	if err != nil {
		return err
	}

	pointsPerPackage := float64(10) / float64(len(updates))

	percent := 30.0

	go func() {
		for {
			line, _, err := bufReader.ReadLine()

			log.Infof("apt: " + string(line))

			if err != nil {
				//log.Infof("ERR:%s", err)
				break
			}

			if strings.HasPrefix(string(line), "Reading package lists") {
				percent = percent + 5.0
			}

			if strings.HasPrefix(string(line), "Building dependency tree") {
				percent = percent + 5.0
			}

			if strings.HasPrefix(string(line), "Reading state information") {
				percent = percent + 5.0
			}

			if strings.HasPrefix(string(line), "Need to get") {
				percent = percent + 5.0
			}

			if strings.HasPrefix(string(line), "Get:") {
				percent = percent + (pointsPerPackage * float64(2))
			}

			if strings.HasPrefix(string(line), "Unpacking ") {
				percent = percent + (pointsPerPackage * float64(2))
			}

			if strings.HasPrefix(string(line), "Setting up ") {
				percent = percent + pointsPerPackage
			}

			u.updateProgress(math.Min(99, percent), "Installing updates", "")

		}
	}()

	if err := cmd.Wait(); err != nil {
		if exiterr, ok := err.(*exec.ExitError); ok {
			// The program has exited with an exit code != 0
			// There is no plattform independent way to retrieve
			// the exit code, but the following will work on Unix
			if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
				log.Infof("installUpdates Bad Exit Status: %d", status.ExitStatus())
				return fmt.Errorf("Failed to install updates. Code:%d", status.ExitStatus())
			}
		} else {
			log.Infof("cmd.Wait: %v", err)
		}
	}

	return nil
}
<commit_msg>Take drivers back out<commit_after>package main

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"math"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"syscall"
	"time"
)

type updateJob struct {
	progress   *Progress
	onProgress chan *Progress
}

func (u *updateJob) start() {

	u.progress = &Progress{
		Running:   true,
		startTime: time.Now(),
	}

	u.updateProgress(0, "Looking for updates", "")

	u.cleanup()

	err := u.setReadWrite(true)
	if err != nil {
		u.updateProgress(0, "Failed to enable disk writing", fmt.Sprintf("Error: %s", err))
		return
	}
	defer u.setReadWrite(false)

	log.Infof("Updating from repositories")

	err = u.updateCache(45, 0, 25)
	if err != nil {
		u.updateProgress(0, "Failed", fmt.Sprintf("Error: %s", err))
		return
	}

	u.updateProgress(27, "Processing available updates", "")

	updates, err := u.getAvailableUpdates()

	if err != nil {
		u.updateProgress(0, "Failed", fmt.Sprintf("Error: %s", err))
		return
	}

	updates = append(updates, AvailableUpdate{
		Name: "ninjasphere", // Always force it
	})

	// Check to see if our "get out of jail free" card has been played
	for _, update := range updates {
		if update.Name == "sphere-idspispopd" {
			err = u.installUpdates([]AvailableUpdate{update})

			if err != nil {
				u.updateProgress(0, "Failed running pre-install script", fmt.Sprintf("Error: %s", err))
				return
			}

			updates, err = u.getAvailableUpdates()

			if err != nil {
				u.updateProgress(0, "Failed", fmt.Sprintf("Error: %s", err))
				return
			}
		}
	}

	u.autoRemove()

	log.Infof("%d packages to update: %v", len(updates), updates)

	if len(updates) > 0 {

		u.updateProgress(30, "Installing updates", "")

		err = u.installUpdates(updates)

		if err != nil {
			u.updateProgress(0, "Failed", fmt.Sprintf("Error: %s", err))
			return
		}
	}

	u.updateProgress(100, "Finished", "")
}

func (u *updateJob) updateProgress(percent float64, description, err string) {

	if percent == 100 || err != "" {
		u.progress.Running = false
	}

	if percent > u.progress.Percent {
		u.progress.Percent = percent
	}

	if err != "" {
		u.progress.Error = &err
	}

	if description != "" {
		u.progress.Description = description
	}

	u.onProgress <- u.progress
}

func (u *updateJob) setReadWrite(writing bool) error {
	if runtime.GOOS != "linux" {
		return nil
	}

	mode := "ro"
	if writing {
		mode = "rw"
	}

	cmd := exec.Command("mount", "-o", "remount,"+mode, "/")

	output, err := cmd.Output()
	log.Infof("Output from mount: %s", output)

	return err
}

func (u *updateJob) updateCache(expectedLines float64, startPercent float64, totalPercent float64) error {

	if runtime.GOOS != "linux" {
		return nil
	}

	updateLines := 0.0

	cmd := exec.Command("apt-get", "update", "-q")

	reader, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}

	bufReader := bufio.NewReader(reader)

	err = cmd.Start()

	if err != nil {
		return err
	}

	for {
		_, _, err := bufReader.ReadLine()

		if err != nil {
			//log.Infof("ERR:%s", err)
			break
		}

		updateLines++
		//cleaned := invalidChar.ReplaceAll([]byte(x[0:n]), []byte(""))

		u.updateProgress(startPercent+math.Min(totalPercent, (updateLines/expectedLines)*totalPercent), "", "")
		//	log.Infof("GOT: |%s| %t", line, isPrefix)
	}

	if err := cmd.Wait(); err != nil {
		if exiterr, ok := err.(*exec.ExitError); ok {
			// The program has exited with an exit code != 0
			// There is no plattform independent way to retrieve
			// the exit code, but the following will work on Unix
			if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
				log.Infof("updateCache Bad Exit Status: %d", status.ExitStatus())
				return fmt.Errorf("Failed to update cache. Code: %d", status.ExitStatus())
			}
		} else {
			log.Infof("Update cache : cmd.Wait: %v", err)
		}
	}

	return nil
}

func (u *updateJob) cleanup() {
	cmd := exec.Command("dpkg", "--configure", "-a")

	output, _ := cmd.Output()

	log.Infof("Output from dpkg: %s", output)

}

func (u *updateJob) autoRemove() {
	cmd := exec.Command("apt-get", "auto-remove")

	output, _ := cmd.Output()

	log.Infof("Output from apt-get autoremove: %s", output)
}

func (u *updateJob) getAvailableUpdates() ([]AvailableUpdate, error) {
	var err error
	var available []byte

	ioutil.WriteFile("./available-updates.sh", []byte(`#!/bin/bash
	  apt-get -s dist-upgrade| awk -F'[][() ]+' '/^Inst/{printf "%s\t%s\t%s\n", $2,$3,$4}'`), os.FileMode(755))

	cmd := exec.Command("./available-updates.sh")

	if runtime.GOOS == "linux" {
		available, err = cmd.Output()
	} else {
		available, err = ioutil.ReadFile("./updates.txt")
	}

	if err != nil {
		return nil, fmt.Errorf("Failed to get updatable packages. Error: %s", err)
	}

	var updates []AvailableUpdate

	for _, line := range strings.Split(string(available), "\n") {
		s := strings.Split(line, "\t")
		if len(s) == 3 && strings.Contains(line, "spheramid") && !strings.Contains(line, "sphere-updates") && !strings.Contains(line, "sphere-setup-assistant") {
			updates = append(updates, AvailableUpdate{s[0], s[1], s[2]})
		}
	}

	if runtime.GOOS == "linux" {
		if err := cmd.Wait(); err != nil {
			if exiterr, ok := err.(*exec.ExitError); ok {
				// The program has exited with an exit code != 0
				// There is no plattform independent way to retrieve
				// the exit code, but the following will work on Unix
				if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
					log.Infof("Bad Exit Status: %d", status.ExitStatus())
					return nil, fmt.Errorf("Failed to get updatable packages. Code: %d", status.ExitStatus())
				}
			} else {
				log.Infof("Get updatable : cmd.Wait: %v", err)
			}
		}
	}

	return updates, nil
}

func (u *updateJob) installUpdates(updates []AvailableUpdate) error {

	var cmd *exec.Cmd
	if runtime.GOOS == "linux" {
		args := []string{"install", "-yy", "-q"}
		for _, update := range updates {
			args = append(args, update.Name)
		}

		log.Infof("Running update command : apt-get %s", strings.Join(args, " "))

		cmd = exec.Command("apt-get", args...)
		cmd.Stderr = os.Stderr
	} else {
		cmd = exec.Command("cat", "./upgrade.txt")
	}

	os.Setenv("DEBIAN_FRONTEND", "noninteractive")

	reader, err := cmd.StdoutPipe()

	bufReader := bufio.NewReader(reader)

	err = cmd.Start()

	if err != nil {
		return err
	}

	pointsPerPackage := float64(10) / float64(len(updates))

	percent := 30.0

	go func() {
		for {
			line, _, err := bufReader.ReadLine()

			log.Infof("apt: " + string(line))

			if err != nil {
				//log.Infof("ERR:%s", err)
				break
			}

			if strings.HasPrefix(string(line), "Reading package lists") {
				percent = percent + 5.0
			}

			if strings.HasPrefix(string(line), "Building dependency tree") {
				percent = percent + 5.0
			}

			if strings.HasPrefix(string(line), "Reading state information") {
				percent = percent + 5.0
			}

			if strings.HasPrefix(string(line), "Need to get") {
				percent = percent + 5.0
			}

			if strings.HasPrefix(string(line), "Get:") {
				percent = percent + (pointsPerPackage * float64(2))
			}

			if strings.HasPrefix(string(line), "Unpacking ") {
				percent = percent + (pointsPerPackage * float64(2))
			}

			if strings.HasPrefix(string(line), "Setting up ") {
				percent = percent + pointsPerPackage
			}

			u.updateProgress(math.Min(99, percent), "Installing updates", "")

		}
	}()

	if err := cmd.Wait(); err != nil {
		if exiterr, ok := err.(*exec.ExitError); ok {
			// The program has exited with an exit code != 0
			// There is no plattform independent way to retrieve
			// the exit code, but the following will work on Unix
			if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
				log.Infof("installUpdates Bad Exit Status: %d", status.ExitStatus())
				return fmt.Errorf("Failed to install updates. Code:%d", status.ExitStatus())
			}
		} else {
			log.Infof("cmd.Wait: %v", err)
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package themis

import (
	"flag"
	"strings"

	"github.com/ngaut/log"
	"github.com/pingcap/go-hbase"
	"github.com/pingcap/go-themis/oracle/oracles"
)

const (
	themisTestTableName string = "themis_test"
)

var (
	testRow = []byte("test_row")
	cf      = []byte("cf")
	q       = []byte("q")
)

var (
	zk           = flag.String("zk", "localhost", "hbase zookeeper info")
	globalOracle = oracles.NewLocalOracle()
)

func newTxn(c hbase.HBaseClient, cfg TxnConfig) Txn {
	txn, err := NewTxnWithConf(c, cfg, globalOracle)
	if err != nil {
		log.Fatal(err)
	}
	return txn
}

func getTestZkHosts() []string {
	zks := strings.Split(*zk, ",")
	if len(zks) == 0 {
		log.Fatal("invalid zk")
	}
	return zks
}

func createHBaseClient() (hbase.HBaseClient, error) {
	flag.Parse()
	cli, err := hbase.NewClient(getTestZkHosts(), "/hbase")
	if err != nil {
		return nil, err
	}
	return cli, nil
}

func createNewTableAndDropOldTable(cli hbase.HBaseClient, tblName string, family string, splits [][]byte) error {
	err := dropTable(cli, tblName)
	if err != nil {
		return err
	}
	t := hbase.NewTableDesciptor(hbase.NewTableNameWithDefaultNS(tblName))
	cf := hbase.NewColumnFamilyDescriptor(family)
	cf.AddAttr("THEMIS_ENABLE", "true")
	t.AddColumnDesc(cf)
	err = cli.CreateTable(t, splits)
	if err != nil {
		return err
	}
	return nil
}

func dropTable(cli hbase.HBaseClient, tblName string) error {
	b, err := cli.TableExists(tblName)
	if err != nil {
		return err
	}
	if !b {
		log.Info("table not exist")
		return nil
	}
	t := hbase.NewTableNameWithDefaultNS(tblName)
	err = cli.DisableTable(t)
	if err != nil {
		return err
	}
	err = cli.DropTable(t)
	if err != nil {
		return err
	}
	return nil
}

func init() {
	// disable unittest annoying log
	log.SetLevelByString("error")
}
<commit_msg>*: fix build.<commit_after>package themis

import (
	"flag"
	"strings"

	"github.com/ngaut/log"
	"github.com/pingcap/go-hbase"
	"github.com/pingcap/go-themis/oracle/oracles"
)

const (
	themisTestTableName string = "themis_test"
)

var (
	testRow = []byte("test_row")
	cf      = []byte("cf")
	q       = []byte("q")
)

var (
	zk           = flag.String("zk", "localhost", "hbase zookeeper info")
	globalOracle = oracles.NewLocalOracle()
)

func newTxn(c hbase.HBaseClient, cfg TxnConfig) Txn {
	txn, err := NewTxnWithConf(c, cfg, globalOracle)
	if err != nil {
		log.Fatal(err)
	}
	return txn
}

func getTestZkHosts() []string {
	zks := strings.Split(*zk, ",")
	if len(zks) == 0 {
		log.Fatal("invalid zk")
	}
	return zks
}

func createHBaseClient() (hbase.HBaseClient, error) {
	flag.Parse()
	cli, err := hbase.NewClient(getTestZkHosts(), "/hbase")
	if err != nil {
		return nil, err
	}
	return cli, nil
}

func createNewTableAndDropOldTable(cli hbase.HBaseClient, tblName string, family string, splits [][]byte) error {
	err := dropTable(cli, tblName)
	if err != nil {
		return err
	}
	t := hbase.NewTableDesciptor(tblName)
	cf := hbase.NewColumnFamilyDescriptor(family)
	cf.AddAttr("THEMIS_ENABLE", "true")
	t.AddColumnDesc(cf)
	err = cli.CreateTable(t, splits)
	if err != nil {
		return err
	}
	return nil
}

func dropTable(cli hbase.HBaseClient, tblName string) error {
	b, err := cli.TableExists(tblName)
	if err != nil {
		return err
	}
	if !b {
		log.Info("table not exist")
		return nil
	}

	err = cli.DisableTable(tblName)
	if err != nil {
		return err
	}
	err = cli.DropTable(tblName)
	if err != nil {
		return err
	}
	return nil
}

func init() {
	// disable unittest annoying log
	log.SetLevelByString("error")
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	_ "embed"
	"encoding/base64"
	"encoding/json"
	"flag"
	"fmt"
	"io/fs"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"go.skia.org/infra/autoroll/go/config"
	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/go/sklog"
	"go.skia.org/infra/go/util"
	"go.skia.org/infra/kube/go/kube_conf_gen_lib"
	"google.golang.org/protobuf/encoding/protojson"
	"google.golang.org/protobuf/encoding/prototext"
)

const (
	// Parent repo name for Google3 rollers.
	GOOGLE3_PARENT_NAME = "Google3"
)

var (
	// backendTemplate is the template used to generate the k8s YAML config file
	// for autoroll backends.
	//go:embed autoroll-be.yaml.template
	backendTemplate string

	// namespaceTemplate is the template used to generate the k8s YAML config
	// file for autoroll namespaces.
	//go:embed autoroll-ns.yaml.template
	namespaceTemplate string

	oldClusters = []string{
		"skia-corp",
		"skia-public",
	}
)

func main() {
	src := flag.String("src", "", "Source directory.")
	dst := flag.String("dst", "", "Destination directory. Outputs will mimic the structure of the source.")

	flag.Parse()

	if *src == "" {
		sklog.Fatal("--src is required.")
	}
	if *dst == "" {
		sklog.Fatal("--dst is required.")
	}
	if backendTemplate == "" {
		sklog.Fatal("internal error; embedded template is empty.")
	}

	ctx := context.Background()
	fsys := os.DirFS(*src)
	if err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error {
		if err != nil {
			return err
		}
		if d.IsDir() {
			return nil
		}
		if strings.HasSuffix(d.Name(), ".cfg") {
			if err := convertConfig(ctx, path, *src, *dst); err != nil {
				return skerr.Wrapf(err, "failed to convert config %s", path)
			}
		}
		return nil
	}); err != nil {
		sklog.Fatalf("Failed to read configs: %s", err)
	}
}

func convertConfig(ctx context.Context, relPath, srcDir, dstDir string) error {
	// Read the config file.
	srcPath := filepath.Join(srcDir, relPath)
	cfgBytes, err := ioutil.ReadFile(srcPath)
	if err != nil {
		return skerr.Wrapf(err, "failed to read roller config %s", srcPath)
	}
	var cfg config.Config
	if err := prototext.Unmarshal(cfgBytes, &cfg); err != nil {
		sklog.Fatalf("failed to parse roller config %s: %s", srcPath, err)
	}
	// Google3 uses a different type of backend.
	if cfg.ParentDisplayName == GOOGLE3_PARENT_NAME {
		return nil
	}

	// kube-conf-gen wants a JSON-ish version of the config in order to build
	// the config map.
	cfgJsonBytes, err := protojson.MarshalOptions{
		AllowPartial:    true,
		EmitUnpopulated: true,
	}.Marshal(&cfg)
	if err != nil {
		return skerr.Wrap(err)
	}
	cfgJson := map[string]interface{}{}
	if err := json.Unmarshal(cfgJsonBytes, &cfgJson); err != nil {
		return skerr.Wrap(err)
	}
	cfgMap := map[string]interface{}{}
	if err := kube_conf_gen_lib.ParseConfigHelper(cfgJson, cfgMap, false); err != nil {
		return skerr.Wrap(err)
	}

	// Encode the roller config file as base64.
	// Note that we could re-read the config file from disk
	// and base64-encode its contents. In practice, the
	// behavior of the autoroll frontend and backends would
	// be the same, so we consider it preferable to encode
	// the parsed config, which will strip things like
	// comments and whitespace that would otherwise produce
	// a "different" config.
	b, err := prototext.MarshalOptions{
		AllowPartial: true,
		EmitUnknown:  true,
	}.Marshal(&cfg)
	if err != nil {
		return skerr.Wrapf(err, "Failed to encode roller config as text proto")
	}
	cfgFileBase64 := base64.StdEncoding.EncodeToString(b)
	cfgMap["configBase64"] = cfgFileBase64

	// Temporary measure to help transition over to the new cluster(s).
	isOldCluster := false
	splitRelPath := strings.Split(relPath, string(filepath.Separator))
	for _, oldCluster := range oldClusters {
		if util.In(oldCluster, splitRelPath) {
			isOldCluster = true
			break
		}
	}
	cfgMap["oldCluster"] = isOldCluster

	// Run kube-conf-gen to generate the backend config file.
	relDir, baseName := filepath.Split(relPath)
	dstPath := filepath.Join(dstDir, relDir, fmt.Sprintf("autoroll-be-%s.yaml", strings.Split(baseName, ".")[0]))
	if err := kube_conf_gen_lib.GenerateOutputFromTemplateString(backendTemplate, false, cfgMap, dstPath); err != nil {
		return skerr.Wrapf(err, "failed to write output")
	}

	// Run kube-conf-gen to generate the namespace config file. Note that we'll
	// overwrite this file for every roller in the namespace, but that shouldn't
	// be a problem, since the generated files will be the same.
	if !isOldCluster {
		namespace := strings.Split(cfg.ServiceAccount, "@")[0]
		dstNsPath := filepath.Join(dstDir, relDir, fmt.Sprintf("%s-ns.yaml", namespace))
		if err := kube_conf_gen_lib.GenerateOutputFromTemplateString(namespaceTemplate, false, cfgMap, dstNsPath); err != nil {
			return skerr.Wrapf(err, "failed to write output")
		}
	}

	return nil
}
<commit_msg>[autoroll] Add some logging to config-converter<commit_after>package main

import (
	"context"
	_ "embed"
	"encoding/base64"
	"encoding/json"
	"flag"
	"fmt"
	"io/fs"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"go.skia.org/infra/autoroll/go/config"
	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/go/sklog"
	"go.skia.org/infra/go/util"
	"go.skia.org/infra/kube/go/kube_conf_gen_lib"
	"google.golang.org/protobuf/encoding/protojson"
	"google.golang.org/protobuf/encoding/prototext"
)

const (
	// Parent repo name for Google3 rollers.
	GOOGLE3_PARENT_NAME = "Google3"
)

var (
	// backendTemplate is the template used to generate the k8s YAML config file
	// for autoroll backends.
	//go:embed autoroll-be.yaml.template
	backendTemplate string

	// namespaceTemplate is the template used to generate the k8s YAML config
	// file for autoroll namespaces.
	//go:embed autoroll-ns.yaml.template
	namespaceTemplate string

	oldClusters = []string{
		"skia-corp",
		"skia-public",
	}
)

func main() {
	src := flag.String("src", "", "Source directory.")
	dst := flag.String("dst", "", "Destination directory. Outputs will mimic the structure of the source.")

	flag.Parse()

	if *src == "" {
		sklog.Fatal("--src is required.")
	}
	if *dst == "" {
		sklog.Fatal("--dst is required.")
	}
	if backendTemplate == "" {
		sklog.Fatal("internal error; embedded template is empty.")
	}

	ctx := context.Background()
	fsys := os.DirFS(*src)
	if err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error {
		if err != nil {
			return err
		}
		if d.IsDir() {
			return nil
		}
		if strings.HasSuffix(d.Name(), ".cfg") {
			if err := convertConfig(ctx, path, *src, *dst); err != nil {
				return skerr.Wrapf(err, "failed to convert config %s", path)
			}
		}
		return nil
	}); err != nil {
		sklog.Fatalf("Failed to read configs: %s", err)
	}
}

func convertConfig(ctx context.Context, relPath, srcDir, dstDir string) error {
	// Read the config file.
	srcPath := filepath.Join(srcDir, relPath)
	sklog.Infof("Converting %s", srcPath)
	cfgBytes, err := ioutil.ReadFile(srcPath)
	if err != nil {
		return skerr.Wrapf(err, "failed to read roller config %s", srcPath)
	}
	var cfg config.Config
	if err := prototext.Unmarshal(cfgBytes, &cfg); err != nil {
		sklog.Fatalf("failed to parse roller config %s: %s", srcPath, err)
	}
	// Google3 uses a different type of backend.
	if cfg.ParentDisplayName == GOOGLE3_PARENT_NAME {
		return nil
	}

	// kube-conf-gen wants a JSON-ish version of the config in order to build
	// the config map.
	cfgJsonBytes, err := protojson.MarshalOptions{
		AllowPartial:    true,
		EmitUnpopulated: true,
	}.Marshal(&cfg)
	if err != nil {
		return skerr.Wrap(err)
	}
	cfgJson := map[string]interface{}{}
	if err := json.Unmarshal(cfgJsonBytes, &cfgJson); err != nil {
		return skerr.Wrap(err)
	}
	cfgMap := map[string]interface{}{}
	if err := kube_conf_gen_lib.ParseConfigHelper(cfgJson, cfgMap, false); err != nil {
		return skerr.Wrap(err)
	}

	// Encode the roller config file as base64.
	// Note that we could re-read the config file from disk
	// and base64-encode its contents. In practice, the
	// behavior of the autoroll frontend and backends would
	// be the same, so we consider it preferable to encode
	// the parsed config, which will strip things like
	// comments and whitespace that would otherwise produce
	// a "different" config.
	b, err := prototext.MarshalOptions{
		AllowPartial: true,
		EmitUnknown:  true,
	}.Marshal(&cfg)
	if err != nil {
		return skerr.Wrapf(err, "Failed to encode roller config as text proto")
	}
	cfgFileBase64 := base64.StdEncoding.EncodeToString(b)
	cfgMap["configBase64"] = cfgFileBase64

	// Temporary measure to help transition over to the new cluster(s).
	isOldCluster := false
	splitRelPath := strings.Split(relPath, string(filepath.Separator))
	for _, oldCluster := range oldClusters {
		if util.In(oldCluster, splitRelPath) {
			isOldCluster = true
			break
		}
	}
	cfgMap["oldCluster"] = isOldCluster

	// Run kube-conf-gen to generate the backend config file.
	relDir, baseName := filepath.Split(relPath)
	dstPath := filepath.Join(dstDir, relDir, fmt.Sprintf("autoroll-be-%s.yaml", strings.Split(baseName, ".")[0]))
	if err := kube_conf_gen_lib.GenerateOutputFromTemplateString(backendTemplate, false, cfgMap, dstPath); err != nil {
		return skerr.Wrapf(err, "failed to write output")
	}
	sklog.Infof("Wrote %s", dstPath)

	// Run kube-conf-gen to generate the namespace config file. Note that we'll
	// overwrite this file for every roller in the namespace, but that shouldn't
	// be a problem, since the generated files will be the same.
	if !isOldCluster {
		namespace := strings.Split(cfg.ServiceAccount, "@")[0]
		dstNsPath := filepath.Join(dstDir, relDir, fmt.Sprintf("%s-ns.yaml", namespace))
		if err := kube_conf_gen_lib.GenerateOutputFromTemplateString(namespaceTemplate, false, cfgMap, dstNsPath); err != nil {
			return skerr.Wrapf(err, "failed to write output")
		}
		sklog.Infof("Wrote %s", dstNsPath)
	}

	return nil
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"regexp"
	"testing"
	"time"

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

func TestAccAWSAutoscalingSchedule_basic(t *testing.T) {
	var schedule autoscaling.ScheduledUpdateGroupAction
	rName := fmt.Sprintf("tf-test-%d", acctest.RandInt())
	start := testAccAWSAutoscalingScheduleValidStart(t)
	end := testAccAWSAutoscalingScheduleValidEnd(t)

	scheduledActionName := "foobar"
	resourceName := fmt.Sprintf("aws_autoscaling_schedule.%s", scheduledActionName)
	importInput := fmt.Sprintf("%s/%s", rName, scheduledActionName)

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAutoscalingScheduleDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAutoscalingScheduleConfig(rName, start, end),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckScalingScheduleExists(resourceName, &schedule),
				),
			},
			{
				ResourceName:      resourceName,
				ImportStateId:     importInput,
				ImportState:       true,
				ImportStateVerify: true,
			},
			{
				ResourceName:      resourceName,
				ImportStateId:     fmt.Sprintf("%s/nonexistent", rName),
				ImportState:       true,
				ImportStateVerify: false,
				ExpectError:       regexp.MustCompile(`(Cannot import non-existent remote object)`),
			},
		},
	})
}

func TestAccAWSAutoscalingSchedule_disappears(t *testing.T) {
	var schedule autoscaling.ScheduledUpdateGroupAction
	rName := fmt.Sprintf("tf-test-%d", acctest.RandInt())
	start := testAccAWSAutoscalingScheduleValidStart(t)
	end := testAccAWSAutoscalingScheduleValidEnd(t)

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAutoscalingScheduleDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAutoscalingScheduleConfig(rName, start, end),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckScalingScheduleExists("aws_autoscaling_schedule.foobar", &schedule),
					testAccCheckScalingScheduleDisappears(&schedule),
				),
				ExpectNonEmptyPlan: true,
			},
		},
	})
}

func testAccCheckScalingScheduleDisappears(schedule *autoscaling.ScheduledUpdateGroupAction) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		autoscalingconn := testAccProvider.Meta().(*AWSClient).autoscalingconn
		params := &autoscaling.DeleteScheduledActionInput{
			AutoScalingGroupName: schedule.AutoScalingGroupName,
			ScheduledActionName:  schedule.ScheduledActionName,
		}
		_, err := autoscalingconn.DeleteScheduledAction(params)
		return err
	}
}

func TestAccAWSAutoscalingSchedule_recurrence(t *testing.T) {
	var schedule autoscaling.ScheduledUpdateGroupAction

	rName := fmt.Sprintf("tf-test-%d", acctest.RandInt())

	scheduledActionName := "foobar"
	resourceName := fmt.Sprintf("aws_autoscaling_schedule.%s", scheduledActionName)
	importInput := fmt.Sprintf("%s/%s", rName, scheduledActionName)

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAutoscalingScheduleDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAutoscalingScheduleConfig_recurrence(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckScalingScheduleExists(resourceName, &schedule),
					resource.TestCheckResourceAttr(resourceName, "recurrence", "0 8 * * *"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportStateId:     importInput,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSAutoscalingSchedule_zeroValues(t *testing.T) {
	var schedule autoscaling.ScheduledUpdateGroupAction

	rName := fmt.Sprintf("tf-test-%d", acctest.RandInt())
	start := testAccAWSAutoscalingScheduleValidStart(t)
	end := testAccAWSAutoscalingScheduleValidEnd(t)

	scheduledActionName := "foobar"
	resourceName := fmt.Sprintf("aws_autoscaling_schedule.%s", scheduledActionName)
	importInput := fmt.Sprintf("%s/%s", rName, scheduledActionName)

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAutoscalingScheduleDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAutoscalingScheduleConfig_zeroValues(rName, start, end),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckScalingScheduleExists(resourceName, &schedule),
				),
			},
			{
				ResourceName:      resourceName,
				ImportStateId:     importInput,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSAutoscalingSchedule_negativeOne(t *testing.T) {
	var schedule autoscaling.ScheduledUpdateGroupAction

	rName := fmt.Sprintf("tf-test-%d", acctest.RandInt())
	start := testAccAWSAutoscalingScheduleValidStart(t)
	end := testAccAWSAutoscalingScheduleValidEnd(t)

	scheduledActionName := "foobar"
	resourceName := fmt.Sprintf("aws_autoscaling_schedule.%s", scheduledActionName)
	importInput := fmt.Sprintf("%s/%s", rName, scheduledActionName)

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAutoscalingScheduleDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAutoscalingScheduleConfig_negativeOne(rName, start, end),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckScalingScheduleExists(resourceName, &schedule),
					testAccCheckScalingScheduleHasNoDesiredCapacity(&schedule),
					resource.TestCheckResourceAttr(resourceName, "desired_capacity", "-1"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportStateId:     importInput,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func testAccAWSAutoscalingScheduleValidEnd(t *testing.T) string {
	return testAccAWSAutoscalingScheduleTime(t, "2h")
}

func testAccAWSAutoscalingScheduleValidStart(t *testing.T) string {
	return testAccAWSAutoscalingScheduleTime(t, "1h")
}

func testAccAWSAutoscalingScheduleTime(t *testing.T, duration string) string {
	n := time.Now().UTC()
	d, err := time.ParseDuration(duration)
	if err != nil {
		t.Fatalf("err parsing time duration: %s", err)
	}
	return n.Add(d).Format(awsAutoscalingScheduleTimeLayout)
}

func testAccCheckScalingScheduleExists(n string, policy *autoscaling.ScheduledUpdateGroupAction) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		autoScalingGroup := rs.Primary.Attributes["autoscaling_group_name"]
		conn := testAccProvider.Meta().(*AWSClient).autoscalingconn
		params := &autoscaling.DescribeScheduledActionsInput{
			AutoScalingGroupName: aws.String(autoScalingGroup),
			ScheduledActionNames: []*string{aws.String(rs.Primary.ID)},
		}

		resp, err := conn.DescribeScheduledActions(params)
		if err != nil {
			return err
		}
		if len(resp.ScheduledUpdateGroupActions) == 0 {
			return fmt.Errorf("Scaling Schedule not found")
		}

		*policy = *resp.ScheduledUpdateGroupActions[0]

		return nil
	}
}

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

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

		autoScalingGroup := rs.Primary.Attributes["autoscaling_group_name"]
		params := &autoscaling.DescribeScheduledActionsInput{
			AutoScalingGroupName: aws.String(autoScalingGroup),
			ScheduledActionNames: []*string{aws.String(rs.Primary.ID)},
		}

		resp, err := conn.DescribeScheduledActions(params)

		if err == nil {
			if len(resp.ScheduledUpdateGroupActions) != 0 &&
				*resp.ScheduledUpdateGroupActions[0].ScheduledActionName == rs.Primary.ID {
				return fmt.Errorf("Scaling Schedule Still Exists: %s", rs.Primary.ID)
			}
		}
	}

	return nil
}

func testAccCheckScalingScheduleHasNoDesiredCapacity(
	schedule *autoscaling.ScheduledUpdateGroupAction) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if schedule.DesiredCapacity == nil {
			return nil
		}
		return fmt.Errorf("Expected not to set desired capacity, got %v",
			aws.Int64Value(schedule.DesiredCapacity))
	}
}

func testAccAWSAutoscalingScheduleConfig(r, start, end string) string {
	return fmt.Sprintf(`
resource "aws_launch_configuration" "foobar" {
  name          = "%s"
  image_id      = "ami-21f78e11"
  instance_type = "t1.micro"
}

resource "aws_autoscaling_group" "foobar" {
  availability_zones        = ["us-west-2a"]
  name                      = "%s"
  max_size                  = 1
  min_size                  = 1
  health_check_grace_period = 300
  health_check_type         = "ELB"
  force_delete              = true
  termination_policies      = ["OldestInstance"]
  launch_configuration      = "${aws_launch_configuration.foobar.name}"

  tag {
    key                 = "Foo"
    value               = "foo-bar"
    propagate_at_launch = true
  }
}

resource "aws_autoscaling_schedule" "foobar" {
  scheduled_action_name  = "foobar"
  min_size               = 0
  max_size               = 1
  desired_capacity       = 0
  start_time             = "%s"
  end_time               = "%s"
  autoscaling_group_name = "${aws_autoscaling_group.foobar.name}"
}
`, r, r, start, end)
}

func testAccAWSAutoscalingScheduleConfig_recurrence(r string) string {
	return fmt.Sprintf(`
resource "aws_launch_configuration" "foobar" {
  name          = "%s"
  image_id      = "ami-21f78e11"
  instance_type = "t1.micro"
}

resource "aws_autoscaling_group" "foobar" {
  availability_zones        = ["us-west-2a"]
  name                      = "%s"
  max_size                  = 1
  min_size                  = 1
  health_check_grace_period = 300
  health_check_type         = "ELB"
  force_delete              = true
  termination_policies      = ["OldestInstance"]
  launch_configuration      = "${aws_launch_configuration.foobar.name}"

  tag {
    key                 = "Foo"
    value               = "foo-bar"
    propagate_at_launch = true
  }
}

resource "aws_autoscaling_schedule" "foobar" {
  scheduled_action_name  = "foobar"
  min_size               = 0
  max_size               = 1
  desired_capacity       = 0
  recurrence             = "0 8 * * *"
  autoscaling_group_name = "${aws_autoscaling_group.foobar.name}"
}
`, r, r)
}

func testAccAWSAutoscalingScheduleConfig_zeroValues(r, start, end string) string {
	return fmt.Sprintf(`
resource "aws_launch_configuration" "foobar" {
  name          = "%s"
  image_id      = "ami-21f78e11"
  instance_type = "t1.micro"
}

resource "aws_autoscaling_group" "foobar" {
  availability_zones        = ["us-west-2a"]
  name                      = "%s"
  max_size                  = 1
  min_size                  = 1
  health_check_grace_period = 300
  health_check_type         = "ELB"
  force_delete              = true
  termination_policies      = ["OldestInstance"]
  launch_configuration      = "${aws_launch_configuration.foobar.name}"

  tag {
    key                 = "Foo"
    value               = "foo-bar"
    propagate_at_launch = true
  }
}

resource "aws_autoscaling_schedule" "foobar" {
  scheduled_action_name  = "foobar"
  max_size               = 0
  min_size               = 0
  desired_capacity       = 0
  start_time             = "%s"
  end_time               = "%s"
  autoscaling_group_name = "${aws_autoscaling_group.foobar.name}"
}
`, r, r, start, end)
}

func testAccAWSAutoscalingScheduleConfig_negativeOne(r, start, end string) string {
	return fmt.Sprintf(`
resource "aws_launch_configuration" "foobar" {
  name          = "%s"
  image_id      = "ami-21f78e11"
  instance_type = "t1.micro"
}

resource "aws_autoscaling_group" "foobar" {
  availability_zones        = ["us-west-2a"]
  name                      = "%s"
  max_size                  = 1
  min_size                  = 1
  health_check_grace_period = 300
  health_check_type         = "ELB"
  force_delete              = true
  termination_policies      = ["OldestInstance"]
  launch_configuration      = "${aws_launch_configuration.foobar.name}"

  tag {
    key                 = "Foo"
    value               = "foo-bar"
    propagate_at_launch = true
  }
}

resource "aws_autoscaling_schedule" "foobar" {
  scheduled_action_name  = "foobar"
  max_size               = 3
  min_size               = 1
  desired_capacity       = -1
  start_time             = "%s"
  end_time               = "%s"
  autoscaling_group_name = "${aws_autoscaling_group.foobar.name}"
}
`, r, r, start, end)
}
<commit_msg>Remove hardcoded AMIs and AZs<commit_after>package aws

import (
	"fmt"
	"regexp"
	"testing"
	"time"

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

func TestAccAWSAutoscalingSchedule_basic(t *testing.T) {
	var schedule autoscaling.ScheduledUpdateGroupAction
	rName := fmt.Sprintf("tf-test-%d", acctest.RandInt())
	start := testAccAWSAutoscalingScheduleValidStart(t)
	end := testAccAWSAutoscalingScheduleValidEnd(t)

	scheduledActionName := "foobar"
	resourceName := fmt.Sprintf("aws_autoscaling_schedule.%s", scheduledActionName)
	importInput := fmt.Sprintf("%s/%s", rName, scheduledActionName)

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAutoscalingScheduleDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAutoscalingScheduleConfig(rName, start, end),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckScalingScheduleExists(resourceName, &schedule),
				),
			},
			{
				ResourceName:      resourceName,
				ImportStateId:     importInput,
				ImportState:       true,
				ImportStateVerify: true,
			},
			{
				ResourceName:      resourceName,
				ImportStateId:     fmt.Sprintf("%s/nonexistent", rName),
				ImportState:       true,
				ImportStateVerify: false,
				ExpectError:       regexp.MustCompile(`(Cannot import non-existent remote object)`),
			},
		},
	})
}

func TestAccAWSAutoscalingSchedule_disappears(t *testing.T) {
	var schedule autoscaling.ScheduledUpdateGroupAction
	rName := fmt.Sprintf("tf-test-%d", acctest.RandInt())
	start := testAccAWSAutoscalingScheduleValidStart(t)
	end := testAccAWSAutoscalingScheduleValidEnd(t)

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAutoscalingScheduleDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAutoscalingScheduleConfig(rName, start, end),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckScalingScheduleExists("aws_autoscaling_schedule.foobar", &schedule),
					testAccCheckScalingScheduleDisappears(&schedule),
				),
				ExpectNonEmptyPlan: true,
			},
		},
	})
}

func testAccCheckScalingScheduleDisappears(schedule *autoscaling.ScheduledUpdateGroupAction) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		autoscalingconn := testAccProvider.Meta().(*AWSClient).autoscalingconn
		params := &autoscaling.DeleteScheduledActionInput{
			AutoScalingGroupName: schedule.AutoScalingGroupName,
			ScheduledActionName:  schedule.ScheduledActionName,
		}
		_, err := autoscalingconn.DeleteScheduledAction(params)
		return err
	}
}

func TestAccAWSAutoscalingSchedule_recurrence(t *testing.T) {
	var schedule autoscaling.ScheduledUpdateGroupAction

	rName := fmt.Sprintf("tf-test-%d", acctest.RandInt())

	scheduledActionName := "foobar"
	resourceName := fmt.Sprintf("aws_autoscaling_schedule.%s", scheduledActionName)
	importInput := fmt.Sprintf("%s/%s", rName, scheduledActionName)

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAutoscalingScheduleDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAutoscalingScheduleConfig_recurrence(rName),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckScalingScheduleExists(resourceName, &schedule),
					resource.TestCheckResourceAttr(resourceName, "recurrence", "0 8 * * *"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportStateId:     importInput,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSAutoscalingSchedule_zeroValues(t *testing.T) {
	var schedule autoscaling.ScheduledUpdateGroupAction

	rName := fmt.Sprintf("tf-test-%d", acctest.RandInt())
	start := testAccAWSAutoscalingScheduleValidStart(t)
	end := testAccAWSAutoscalingScheduleValidEnd(t)

	scheduledActionName := "foobar"
	resourceName := fmt.Sprintf("aws_autoscaling_schedule.%s", scheduledActionName)
	importInput := fmt.Sprintf("%s/%s", rName, scheduledActionName)

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAutoscalingScheduleDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAutoscalingScheduleConfig_zeroValues(rName, start, end),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckScalingScheduleExists(resourceName, &schedule),
				),
			},
			{
				ResourceName:      resourceName,
				ImportStateId:     importInput,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccAWSAutoscalingSchedule_negativeOne(t *testing.T) {
	var schedule autoscaling.ScheduledUpdateGroupAction

	rName := fmt.Sprintf("tf-test-%d", acctest.RandInt())
	start := testAccAWSAutoscalingScheduleValidStart(t)
	end := testAccAWSAutoscalingScheduleValidEnd(t)

	scheduledActionName := "foobar"
	resourceName := fmt.Sprintf("aws_autoscaling_schedule.%s", scheduledActionName)
	importInput := fmt.Sprintf("%s/%s", rName, scheduledActionName)

	resource.ParallelTest(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSAutoscalingScheduleDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccAWSAutoscalingScheduleConfig_negativeOne(rName, start, end),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckScalingScheduleExists(resourceName, &schedule),
					testAccCheckScalingScheduleHasNoDesiredCapacity(&schedule),
					resource.TestCheckResourceAttr(resourceName, "desired_capacity", "-1"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportStateId:     importInput,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func testAccAWSAutoscalingScheduleValidEnd(t *testing.T) string {
	return testAccAWSAutoscalingScheduleTime(t, "2h")
}

func testAccAWSAutoscalingScheduleValidStart(t *testing.T) string {
	return testAccAWSAutoscalingScheduleTime(t, "1h")
}

func testAccAWSAutoscalingScheduleTime(t *testing.T, duration string) string {
	n := time.Now().UTC()
	d, err := time.ParseDuration(duration)
	if err != nil {
		t.Fatalf("err parsing time duration: %s", err)
	}
	return n.Add(d).Format(awsAutoscalingScheduleTimeLayout)
}

func testAccCheckScalingScheduleExists(n string, policy *autoscaling.ScheduledUpdateGroupAction) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		autoScalingGroup := rs.Primary.Attributes["autoscaling_group_name"]
		conn := testAccProvider.Meta().(*AWSClient).autoscalingconn
		params := &autoscaling.DescribeScheduledActionsInput{
			AutoScalingGroupName: aws.String(autoScalingGroup),
			ScheduledActionNames: []*string{aws.String(rs.Primary.ID)},
		}

		resp, err := conn.DescribeScheduledActions(params)
		if err != nil {
			return err
		}
		if len(resp.ScheduledUpdateGroupActions) == 0 {
			return fmt.Errorf("Scaling Schedule not found")
		}

		*policy = *resp.ScheduledUpdateGroupActions[0]

		return nil
	}
}

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

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

		autoScalingGroup := rs.Primary.Attributes["autoscaling_group_name"]
		params := &autoscaling.DescribeScheduledActionsInput{
			AutoScalingGroupName: aws.String(autoScalingGroup),
			ScheduledActionNames: []*string{aws.String(rs.Primary.ID)},
		}

		resp, err := conn.DescribeScheduledActions(params)

		if err == nil {
			if len(resp.ScheduledUpdateGroupActions) != 0 &&
				*resp.ScheduledUpdateGroupActions[0].ScheduledActionName == rs.Primary.ID {
				return fmt.Errorf("Scaling Schedule Still Exists: %s", rs.Primary.ID)
			}
		}
	}

	return nil
}

func testAccCheckScalingScheduleHasNoDesiredCapacity(
	schedule *autoscaling.ScheduledUpdateGroupAction) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		if schedule.DesiredCapacity == nil {
			return nil
		}
		return fmt.Errorf("Expected not to set desired capacity, got %v",
			aws.Int64Value(schedule.DesiredCapacity))
	}
}

func testAccAWSAutoscalingScheduleConfig(r, start, end string) string {
	return testAccLatestAmazonLinuxHvmEbsAmiConfig() + fmt.Sprintf(`
resource "aws_launch_configuration" "foobar" {
  name          = "%s"
  image_id      = data.aws_ami.amzn-ami-minimal-hvm-ebs.id
  instance_type = "t1.micro"
}

data "aws_availability_zones" "available" {
  state = "available"

  filter {
    name   = "opt-in-status"
    values = ["opt-in-not-required"]
  }
}

resource "aws_autoscaling_group" "foobar" {
  availability_zones        = [data.aws_availability_zones.available.names[1]]
  name                      = "%s"
  max_size                  = 1
  min_size                  = 1
  health_check_grace_period = 300
  health_check_type         = "ELB"
  force_delete              = true
  termination_policies      = ["OldestInstance"]
  launch_configuration      = "${aws_launch_configuration.foobar.name}"

  tag {
    key                 = "Foo"
    value               = "foo-bar"
    propagate_at_launch = true
  }
}

resource "aws_autoscaling_schedule" "foobar" {
  scheduled_action_name  = "foobar"
  min_size               = 0
  max_size               = 1
  desired_capacity       = 0
  start_time             = "%s"
  end_time               = "%s"
  autoscaling_group_name = "${aws_autoscaling_group.foobar.name}"
}
`, r, r, start, end)
}

func testAccAWSAutoscalingScheduleConfig_recurrence(r string) string {
	return testAccLatestAmazonLinuxHvmEbsAmiConfig() + fmt.Sprintf(`
resource "aws_launch_configuration" "foobar" {
  name          = "%s"
  image_id      = data.aws_ami.amzn-ami-minimal-hvm-ebs.id
  instance_type = "t1.micro"
}

data "aws_availability_zones" "available" {
  state = "available"

  filter {
    name   = "opt-in-status"
    values = ["opt-in-not-required"]
  }
}

resource "aws_autoscaling_group" "foobar" {
  availability_zones        = [data.aws_availability_zones.available.names[1]]
  name                      = "%s"
  max_size                  = 1
  min_size                  = 1
  health_check_grace_period = 300
  health_check_type         = "ELB"
  force_delete              = true
  termination_policies      = ["OldestInstance"]
  launch_configuration      = "${aws_launch_configuration.foobar.name}"

  tag {
    key                 = "Foo"
    value               = "foo-bar"
    propagate_at_launch = true
  }
}

resource "aws_autoscaling_schedule" "foobar" {
  scheduled_action_name  = "foobar"
  min_size               = 0
  max_size               = 1
  desired_capacity       = 0
  recurrence             = "0 8 * * *"
  autoscaling_group_name = "${aws_autoscaling_group.foobar.name}"
}
`, r, r)
}

func testAccAWSAutoscalingScheduleConfig_zeroValues(r, start, end string) string {
	return testAccLatestAmazonLinuxHvmEbsAmiConfig() + fmt.Sprintf(`
resource "aws_launch_configuration" "foobar" {
  name          = "%s"
  image_id      = data.aws_ami.amzn-ami-minimal-hvm-ebs.id
  instance_type = "t1.micro"
}

data "aws_availability_zones" "available" {
  state = "available"

  filter {
    name   = "opt-in-status"
    values = ["opt-in-not-required"]
  }
}

resource "aws_autoscaling_group" "foobar" {
  availability_zones        = [data.aws_availability_zones.available.names[1]]
  name                      = "%s"
  max_size                  = 1
  min_size                  = 1
  health_check_grace_period = 300
  health_check_type         = "ELB"
  force_delete              = true
  termination_policies      = ["OldestInstance"]
  launch_configuration      = "${aws_launch_configuration.foobar.name}"

  tag {
    key                 = "Foo"
    value               = "foo-bar"
    propagate_at_launch = true
  }
}

resource "aws_autoscaling_schedule" "foobar" {
  scheduled_action_name  = "foobar"
  max_size               = 0
  min_size               = 0
  desired_capacity       = 0
  start_time             = "%s"
  end_time               = "%s"
  autoscaling_group_name = "${aws_autoscaling_group.foobar.name}"
}
`, r, r, start, end)
}

func testAccAWSAutoscalingScheduleConfig_negativeOne(r, start, end string) string {
	return testAccLatestAmazonLinuxHvmEbsAmiConfig() + fmt.Sprintf(`
resource "aws_launch_configuration" "foobar" {
  name          = "%s"
  image_id      = data.aws_ami.amzn-ami-minimal-hvm-ebs.id
  instance_type = "t1.micro"
}

data "aws_availability_zones" "available" {
  state = "available"

  filter {
    name   = "opt-in-status"
    values = ["opt-in-not-required"]
  }
}

resource "aws_autoscaling_group" "foobar" {
  availability_zones        = [data.aws_availability_zones.available.names[1]]
  name                      = "%s"
  max_size                  = 1
  min_size                  = 1
  health_check_grace_period = 300
  health_check_type         = "ELB"
  force_delete              = true
  termination_policies      = ["OldestInstance"]
  launch_configuration      = "${aws_launch_configuration.foobar.name}"

  tag {
    key                 = "Foo"
    value               = "foo-bar"
    propagate_at_launch = true
  }
}

resource "aws_autoscaling_schedule" "foobar" {
  scheduled_action_name  = "foobar"
  max_size               = 3
  min_size               = 1
  desired_capacity       = -1
  start_time             = "%s"
  end_time               = "%s"
  autoscaling_group_name = "${aws_autoscaling_group.foobar.name}"
}
`, r, r, start, end)
}
<|endoftext|>


<commit_before>// errchk $G $D/$F.go

// Copyright 2009 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.

// make sure that even if a file imports runtime,
// it cannot get at the low-level runtime definitions
// known to the compiler.  for normal packages
// the compiler doesn't even record the lower case
// functions in its symbol table, but some functions
// in runtime are hard-coded into the compiler.

package main

import "runtime"

func main() {
	runtime.printbool(true);	// ERROR "cannot refer|undefined identifier"
}
<commit_msg>New gccgo error message; match both compilers with one string.<commit_after>// errchk $G $D/$F.go

// Copyright 2009 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.

// make sure that even if a file imports runtime,
// it cannot get at the low-level runtime definitions
// known to the compiler.  for normal packages
// the compiler doesn't even record the lower case
// functions in its symbol table, but some functions
// in runtime are hard-coded into the compiler.

package main

import "runtime"

func main() {
	runtime.printbool(true);	// ERROR "unexported"
}
<|endoftext|>


<commit_before>package util

import (
	"golang.org/x/crypto/bcrypt"
)

// HashString returns a hashed string and an error
func HashString(password string) (string, error) {
	key, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return "", err
	}

	return string(key), nil
}

// HashBytes returns a hashed byte array and an error
func HashBytes(password []byte) ([]byte, error) {
	key, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
	if err != nil {
		return nil, err
	}

	return key, nil
}

// MatchBytes returns true if the hash matches the password
func MatchBytes(hash, password []byte) bool {
	err := bcrypt.CompareHashAndPassword(hash, password)
	if err == nil {
		return true
	}

	return false
}

// MatchString returns true if the hash matches the password
func MatchString(hash, password string) bool {
	return MatchBytes([]byte(hash), []byte(password))
}
<commit_msg>Renamed some variables in the util package<commit_after>package util

import (
	"golang.org/x/crypto/bcrypt"
)

// HashString returns a hashed string and an error
func HashString(data string) (string, error) {
	key, err := bcrypt.GenerateFromPassword([]byte(data), bcrypt.DefaultCost)
	if err != nil {
		return "", err
	}

	return string(key), nil
}

// HashBytes returns a hashed byte array and an error
func HashBytes(data []byte) ([]byte, error) {
	key, err := bcrypt.GenerateFromPassword(data, bcrypt.DefaultCost)
	if err != nil {
		return nil, err
	}

	return key, nil
}

// MatchBytes returns true if the hash matches the password
func MatchBytes(hash, data []byte) bool {
	err := bcrypt.CompareHashAndPassword(hash, data)
	if err == nil {
		return true
	}

	return false
}

// MatchString returns true if the hash matches the password
func MatchString(hash, data string) bool {
	return MatchBytes([]byte(hash), []byte(data))
}
<|endoftext|>


<commit_before>// Copyright 2013 com 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 utl

import (
	"strings"
)

// AppendStr appends string to slice with no duplicates.
func AppendStr(strs []string, str string) []string {
	for _, s := range strs {
		if s == str {
			return strs
		}
	}
	return append(strs, str)
}

// CompareSliceStr compares two 'string' type slices.
// It returns true if elements and order are both the same.
func CompareSliceStr(s1, s2 []string) bool {
	if len(s1) != len(s2) {
		return false
	}

	for i := range s1 {
		if s1[i] != s2[i] {
			return false
		}
	}

	return true
}

// CompareSliceStr compares two 'string' type slices.
// It returns true if elements are the same, and ignores the order.
func CompareSliceStrU(s1, s2 []string) bool {
	if len(s1) != len(s2) {
		return false
	}

	for i := range s1 {
		for j := len(s2) - 1; j >= 0; j-- {
			if s1[i] == s2[j] {
				s2 = append(s2[:j], s2[j+1:]...)
				break
			}
		}
	}
	if len(s2) > 0 {
		return false
	}
	return true
}

// IsSliceContainsStr returns true if the string exists in given slice, ignore case.
func IsSliceContainsStr(sl []string, str string) bool {
	str = strings.ToLower(str)
	for _, s := range sl {
		if strings.ToLower(s) == str {
			return true
		}
	}
	return false
}

// IsSliceContainsInt64 returns true if the int64 exists in given slice.
func IsSliceContainsInt64(sl []int64, i int64) bool {
	for _, s := range sl {
		if s == i {
			return true
		}
	}
	return false
}
<commit_msg>add new utl func<commit_after>// Copyright 2013 com 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 utl

import (
	"strconv"
	"strings"
)

// AppendStr appends string to slice with no duplicates.
func AppendStr(strs []string, str string) []string {
	for _, s := range strs {
		if s == str {
			return strs
		}
	}
	return append(strs, str)
}

// CompareSliceStr compares two 'string' type slices.
// It returns true if elements and order are both the same.
func CompareSliceStr(s1, s2 []string) bool {
	if len(s1) != len(s2) {
		return false
	}

	for i := range s1 {
		if s1[i] != s2[i] {
			return false
		}
	}

	return true
}

// CompareSliceStr compares two 'string' type slices.
// It returns true if elements are the same, and ignores the order.
func CompareSliceStrU(s1, s2 []string) bool {
	if len(s1) != len(s2) {
		return false
	}

	for i := range s1 {
		for j := len(s2) - 1; j >= 0; j-- {
			if s1[i] == s2[j] {
				s2 = append(s2[:j], s2[j+1:]...)
				break
			}
		}
	}
	if len(s2) > 0 {
		return false
	}
	return true
}

// IsSliceContainsStr returns true if the string exists in given slice, ignore case.
func IsSliceContainsStr(sl []string, str string) bool {
	str = strings.ToLower(str)
	for _, s := range sl {
		if strings.ToLower(s) == str {
			return true
		}
	}
	return false
}

// IsSliceContainsInt64 returns true if the int64 exists in given slice.
func IsSliceContainsInt64(sl []int64, i int64) bool {
	for _, s := range sl {
		if s == i {
			return true
		}
	}
	return false
}

func StringSliceToInt64Slice(sl []string) []int64 {
	var ret []int64
	for _, v := range sl {
		i, _ := strconv.ParseInt(v, 10, 64)
		ret = append(ret, i)
	}
	return ret
}

func Int64SliceToStringSlice(sl []int64) []string {
	var ret []string
	for _, v := range sl {
		ret = append(ret, strconv.FormatInt(v, 10))
	}
	return ret
}
<|endoftext|>


<commit_before>package colonycore

import (
	"github.com/eaciit/orm/v1"
    "github.com/eaciit/toolkit"
)

type Server struct {
	orm.ModelBase
	ID         string `json:"_id", bson:"_id"`
	OS         string `json:"os", bson:"os"`
	AppPath    string `json:"appPath",bson:"appPath"`
	DataPath   string `json:"dataPath",bson:"dataPath"`
	Host       string `json:"host", bson:"host"`
	ServerType string `json:"serverType", bson:"serverType"`
	SSHType    string `json:"sshtype", bson:"sshtype"`
	SSHFile    string `json:"sshfile", bson:"sshfile"`
	SSHUser    string `json:"sshuser", bson:"sshuser"`
	SSHPass    string `json:"sshpass", bson:"sshpass"`
	CmdExtract string `json:"cmdextract", bson:"cmdextract"`
	CmdNewFile string `json:"cmdnewfile", bson:"cmdnewfile"`
	CmdCopy    string `json:"cmdcopy", bson:"cmdcopy"`
	CmdMkDir   string `json:"cmdmkdir", bson:"cmdmkdir"`
    HostAlias  toolkit.M `json:"hostAlias", bson:"hostAlias"`
}

func (s *Server) TableName() string {
	return "servers"
}

func (s *Server) RecordID() interface{} {
	return s.ID
}
<commit_msg>no message<commit_after>package colonycore

import (
	"github.com/eaciit/orm/v1"
)

type Server struct {
	orm.ModelBase
	ID         string `json:"_id", bson:"_id"`
	OS         string `json:"os", bson:"os"`
	AppPath    string `json:"appPath",bson:"appPath"`
	DataPath   string `json:"dataPath",bson:"dataPath"`
	Host       string `json:"host", bson:"host"`
	ServerType string `json:"serverType", bson:"serverType"`
	SSHType    string `json:"sshtype", bson:"sshtype"`
	SSHFile    string `json:"sshfile", bson:"sshfile"`
	SSHUser    string `json:"sshuser", bson:"sshuser"`
	SSHPass    string `json:"sshpass", bson:"sshpass"`
	CmdExtract string `json:"cmdextract", bson:"cmdextract"`
	CmdNewFile string `json:"cmdnewfile", bson:"cmdnewfile"`
	CmdCopy    string `json:"cmdcopy", bson:"cmdcopy"`
	CmdMkDir   string `json:"cmdmkdir", bson:"cmdmkdir"`
    HostAlias  []*HostAlias `json:"hostAlias", bson:"hostAlias"`
}

type HostAlias struct {
    IP       string `json:"ip", bson:"ip"`
    HostName string `json:"hostName", bson:"hostName"`
}

func (s *Server) TableName() string {
	return "servers"
}

func (s *Server) RecordID() interface{} {
	return s.ID
}
<|endoftext|>


<commit_before>package syntaxfile

import "text/scanner"
import u "unicode"
import "fmt"
import "strconv"
import "io"

func firstLetter(s string) rune {
	for _,r := range s { return r }
	return 0
}

type sfparser struct{
	s scanner.Scanner
	t rune
}
func (s* sfparser) next() {
	if s.t == scanner.EOF { return }
	s.t = s.s.Scan()
}
func (s* sfparser) assert(ex string) {
	if ex==s.s.TokenText() { return }
	fmt.Println(s.s.Pos(),": expected ",ex," but got ",s.s.TokenText())
	panic("SoftPanic: syntax")
}
func (s* sfparser) unquote() string {
	t,_ := strconv.Unquote(s.s.TokenText())
	return t
}

func (s* sfparser) rule0(m *Modifier) {
	for {
		switch s.t {
		case scanner.Ident:
			ident := s.s.TokenText()
			s.next()
			if u.IsUpper(firstLetter(ident)) {
				m.Data = append(m.Data,&MatchToken{ident})
			}else{
				m.Data = append(m.Data,&CallRule{ident})
			}
		case scanner.String:
			m.Data = append(m.Data,&MatchText{s.unquote()})
			s.next()
		case '+','*','?':
			modp := len(m.Data)-1
			if modp>=0 {
				m.Data[modp] = &Modifier{[]Rule{m.Data[modp]},byte(s.t),0}
			}
			s.next()
		case '(':
			s.next()
			m.Data = append(m.Data,s.rule())
			s.assert(")")
			s.next()
		case '~':
			s.next()
			s.assert("(")
			s.next() // (
			gn := ""
			switch s.t {
			case scanner.RawString,scanner.String:
				gn = s.unquote()
				s.next()
			case ':',',':s.next()
			}
			m.Data = append(m.Data,&Group{s.rule(),gn})
			s.assert(")")
			s.next() // )
		case '#':
			s.next()
			aty := s.s.TokenText()
			atyp := len(m.Data)-1
			s.next()
			if atyp>=0 {
				switch aty{
				case "-":
					m.Data[atyp] = &Modifier{[]Rule{m.Data[atyp]},M_DROP,0}
				case "e","verbose":
					if _,ok := m.Data[atyp].(*Modifier); ok {
						m.Data[atyp].(*Modifier).Flags |= F_VERBOSE
					}
				case "E","mute":
					if _,ok := m.Data[atyp].(*Modifier); !ok {
						m.Data[atyp] = &Modifier{[]Rule{m.Data[atyp]},M_SEQ,0}
					}
					m.Data[atyp].(*Modifier).Flags |= F_MUTE
				case "p","precise":
					m.Data[atyp] = &Modifier{[]Rule{m.Data[atyp]},M_SEQ,0}
				}
			}
		default: return
		}
	}
}

func (s* sfparser) rule1(m *Modifier) {
	md := &Modifier{Mode: M_SEQ}
	s.rule0(md)
	for {
		switch s.t {
		case '|':
			s.next()
			m.Data = append(m.Data,md)
			md = &Modifier{Mode: M_SEQ}
			s.rule0(md)
		default:
			m.Data = append(m.Data,md)
			return
		}
	}
}

func (s* sfparser) rule() Rule {
	md := &Modifier{Mode: M_OR}
	s.rule1(md)
	return md
}

func (s* sfparser) parse() SyntaxFile {
	sf := make(SyntaxFile)
	for s.t!=scanner.EOF {
		t := s.s.TokenText()
		s.next()
		s.assert("=")
		s.next()
		r := s.rule()
		s.assert(";")
		s.next()
		sf[t]=r
	}
	return sf
}

// Parses an SyntaxFile. On Syntax error it panics.
func Parse(src io.Reader) SyntaxFile {
	sf := &sfparser{}
	sf.s.Init(src)
	sf.next()
	return sf.parse()
}

<commit_msg>bugfix<commit_after>package syntaxfile

import "text/scanner"
import u "unicode"
import "fmt"
import "strconv"
import "io"

func firstLetter(s string) rune {
	for _,r := range s { return r }
	return 0
}

type sfparser struct{
	s scanner.Scanner
	t rune
}
func (s* sfparser) next() {
	if s.t == scanner.EOF { return }
	s.t = s.s.Scan()
}
func (s* sfparser) assert(ex string) {
	if ex==s.s.TokenText() { return }
	fmt.Println(s.s.Pos(),": expected ",ex," but got ",s.s.TokenText())
	panic("SoftPanic: syntax")
}
func (s* sfparser) unquote() string {
	t,_ := strconv.Unquote(s.s.TokenText())
	return t
}

func (s* sfparser) rule0(m *Modifier) {
	for {
		switch s.t {
		case scanner.Ident:
			ident := s.s.TokenText()
			s.next()
			if u.IsUpper(firstLetter(ident)) {
				m.Data = append(m.Data,&MatchToken{ident})
			}else{
				m.Data = append(m.Data,&CallRule{ident})
			}
		case scanner.String:
			m.Data = append(m.Data,&MatchText{s.unquote()})
			s.next()
		case '+','*','?':
			modp := len(m.Data)-1
			if modp>=0 {
				m.Data[modp] = &Modifier{[]Rule{m.Data[modp]},byte(s.t),0}
			}
			s.next()
		case '(':
			s.next()
			m.Data = append(m.Data,s.rule())
			s.assert(")")
			s.next()
		case '~':
			s.next()
			s.assert("(")
			s.next() // (
			gn := ""
			switch s.t {
			case scanner.RawString,scanner.String:
				gn = s.unquote()
				s.next()
			case ':',',':s.next()
			}
			m.Data = append(m.Data,&Group{s.rule(),gn})
			s.assert(")")
			s.next() // )
		case '#':
			s.next()
			aty := s.s.TokenText()
			atyp := len(m.Data)-1
			s.next()
			if atyp>=0 {
				switch aty{
				case "-":
					m.Data[atyp] = &Modifier{[]Rule{m.Data[atyp]},M_DROP,0}
				case "e","verbose":
					if _,ok := m.Data[atyp].(*Modifier); ok {
						m.Data[atyp].(*Modifier).Flags |= F_VERBOSE
					}
				case "E","mute":
					if _,ok := m.Data[atyp].(*Modifier); !ok {
						m.Data[atyp] = &Modifier{[]Rule{m.Data[atyp]},M_SEQ,0}
					}
					m.Data[atyp].(*Modifier).Flags |= F_MUTE
				case "p","precise":
					m.Data[atyp] = &Modifier{[]Rule{m.Data[atyp]},M_OMIT_VERBOSITY,0}
				}
			}
		default: return
		}
	}
}

func (s* sfparser) rule1(m *Modifier) {
	md := &Modifier{Mode: M_SEQ}
	s.rule0(md)
	for {
		switch s.t {
		case '|':
			s.next()
			m.Data = append(m.Data,md)
			md = &Modifier{Mode: M_SEQ}
			s.rule0(md)
		default:
			m.Data = append(m.Data,md)
			return
		}
	}
}

func (s* sfparser) rule() Rule {
	md := &Modifier{Mode: M_OR}
	s.rule1(md)
	return md
}

func (s* sfparser) parse() SyntaxFile {
	sf := make(SyntaxFile)
	for s.t!=scanner.EOF {
		t := s.s.TokenText()
		s.next()
		s.assert("=")
		s.next()
		r := s.rule()
		s.assert(";")
		s.next()
		sf[t]=r
	}
	return sf
}

// Parses an SyntaxFile. On Syntax error it panics.
func Parse(src io.Reader) SyntaxFile {
	sf := &sfparser{}
	sf.s.Init(src)
	sf.next()
	return sf.parse()
}

<|endoftext|>


<commit_before>// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

package uuid

import (
	"bytes"
	"fmt"
	"testing"
	"time"
)

func TestUUID(t *testing.T) {
	t.Run("Bytes", testUUIDBytes)
	t.Run("String", testUUIDString)
	t.Run("Version", testUUIDVersion)
	t.Run("Variant", testUUIDVariant)
	t.Run("SetVersion", testUUIDSetVersion)
	t.Run("SetVariant", testUUIDSetVariant)
	t.Run("Format", testUUIDFormat)
}

func testUUIDBytes(t *testing.T) {
	got := codecTestUUID.Bytes()
	want := codecTestData
	if !bytes.Equal(got, want) {
		t.Errorf("%v.Bytes() = %x, want %x", codecTestUUID, got, want)
	}
}

func testUUIDString(t *testing.T) {
	got := NamespaceDNS.String()
	want := "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
	if got != want {
		t.Errorf("%v.String() = %q, want %q", NamespaceDNS, got, want)
	}
}

func testUUIDVersion(t *testing.T) {
	u := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
	if got, want := u.Version(), V1; got != want {
		t.Errorf("%v.Version() == %d, want %d", u, got, want)
	}
}

func testUUIDVariant(t *testing.T) {
	tests := []struct {
		u    UUID
		want byte
	}{
		{
			u:    UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
			want: VariantNCS,
		},
		{
			u:    UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
			want: VariantRFC4122,
		},
		{
			u:    UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
			want: VariantMicrosoft,
		},
		{
			u:    UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
			want: VariantFuture,
		},
	}
	for _, tt := range tests {
		if got := tt.u.Variant(); got != tt.want {
			t.Errorf("%v.Variant() == %d, want %d", tt.u, got, tt.want)
		}
	}
}

func testUUIDSetVersion(t *testing.T) {
	u := UUID{}
	want := V4
	u.SetVersion(want)
	if got := u.Version(); got != want {
		t.Errorf("%v.Version() == %d after SetVersion(%d)", u, got, want)
	}
}

func testUUIDSetVariant(t *testing.T) {
	variants := []byte{
		VariantNCS,
		VariantRFC4122,
		VariantMicrosoft,
		VariantFuture,
	}
	for _, want := range variants {
		u := UUID{}
		u.SetVariant(want)
		if got := u.Variant(); got != want {
			t.Errorf("%v.Variant() == %d after SetVariant(%d)", u, got, want)
		}
	}
}

func testUUIDFormat(t *testing.T) {
	val := Must(FromString("12345678-90ab-cdef-1234-567890abcdef"))
	tests := []struct {
		u    UUID
		f    string
		want string
	}{
		{u: val, f: "%s", want: "12345678-90ab-cdef-1234-567890abcdef"},
		{u: val, f: "%q", want: `"12345678-90ab-cdef-1234-567890abcdef"`},
		{u: val, f: "%x", want: "1234567890abcdef1234567890abcdef"},
		{u: val, f: "%X", want: "1234567890ABCDEF1234567890ABCDEF"},
		{u: val, f: "%v", want: "12345678-90ab-cdef-1234-567890abcdef"},
		{u: val, f: "%+v", want: "12345678-90ab-cdef-1234-567890abcdef"},
		{u: val, f: "%#v", want: "12345678-90ab-cdef-1234-567890abcdef"},
		{u: val, f: "%T", want: "uuid.UUID"},
		{u: val, f: "%t", want: ""},
		{u: val, f: "%b", want: ""},
		{u: val, f: "%c", want: ""},
		{u: val, f: "%d", want: ""},
		{u: val, f: "%e", want: ""},
		{u: val, f: "%E", want: ""},
		{u: val, f: "%f", want: ""},
		{u: val, f: "%F", want: ""},
		{u: val, f: "%g", want: ""},
		{u: val, f: "%G", want: ""},
		{u: val, f: "%o", want: ""},
		{u: val, f: "%U", want: ""},
		// TODO: dylan-bourque - 2019-02-18
		// uuid.Format() does not get called so it doesn't seem possible to control/verify the
		// output of these verbs
		//{u: val, f: "%p", want: ""},
		//{u: val, f: "%#p", want: ""},
	}
	for _, tt := range tests {
		got := fmt.Sprintf(tt.f, tt.u)
		if tt.want != got {
			t.Errorf("Format(\"%s\") got %s, want %s", tt.f, got, tt.want)
		}
	}
}

func TestMust(t *testing.T) {
	sentinel := fmt.Errorf("uuid: sentinel error")
	defer func() {
		r := recover()
		if r == nil {
			t.Fatalf("did not panic, want %v", sentinel)
		}
		err, ok := r.(error)
		if !ok {
			t.Fatalf("panicked with %T, want error (%v)", r, sentinel)
		}
		if err != sentinel {
			t.Fatalf("panicked with %v, want %v", err, sentinel)
		}
	}()
	fn := func() (UUID, error) {
		return Nil, sentinel
	}
	Must(fn())
}

func TestTimeFromTimestamp(t *testing.T) {
	tests := []struct {
		t    Timestamp
		want time.Time
	}{
		// a zero timestamp represents October 15, 1582 at midnight UTC
		{t: Timestamp(0), want: time.Date(1582, 10, 15, 0, 0, 0, 0, time.UTC)},
		// a one value is 100ns later
		{t: Timestamp(1), want: time.Date(1582, 10, 15, 0, 0, 0, 100, time.UTC)},
		// 10 million 100ns intervals later is one second
		{t: Timestamp(10000000), want: time.Date(1582, 10, 15, 0, 0, 1, 0, time.UTC)},
		{t: Timestamp(60 * 10000000), want: time.Date(1582, 10, 15, 0, 1, 0, 0, time.UTC)},
		{t: Timestamp(60 * 60 * 10000000), want: time.Date(1582, 10, 15, 1, 0, 0, 0, time.UTC)},
		{t: Timestamp(24 * 60 * 60 * 10000000), want: time.Date(1582, 10, 16, 0, 0, 0, 0, time.UTC)},
		{t: Timestamp(365 * 24 * 60 * 60 * 10000000), want: time.Date(1583, 10, 15, 0, 0, 0, 0, time.UTC)},
		// maximum timestamp value in a UUID is the year 5236
		{t: Timestamp(uint64(1<<60 - 1)), want: time.Date(5236, 03, 31, 21, 21, 0, 684697500, time.UTC)},
	}
	for _, tt := range tests {
		got, _ := tt.t.Time()
		if !got.Equal(tt.want) {
			t.Errorf("%v.Time() == %v, want %v", tt.t, got, tt.want)
		}
	}
}

func TestTimestampFromV1(t *testing.T) {
	tests := []struct {
		u       UUID
		want    Timestamp
		wanterr bool
	}{
		{u: Must(NewV4()), wanterr: true},
		{u: Must(FromString("00000000-0000-1000-0000-000000000000")), want: 0},
		{u: Must(FromString("424f137e-a2aa-11e8-98d0-529269fb1459")), want: 137538640775418750},
		{u: Must(FromString("ffffffff-ffff-1fff-ffff-ffffffffffff")), want: Timestamp(1<<60 - 1)},
	}
	for _, tt := range tests {
		got, goterr := TimestampFromV1(tt.u)
		if tt.wanterr && goterr == nil {
			t.Errorf("TimestampFromV1(%v) want error, got %v", tt.u, got)
		} else if tt.want != got {
			t.Errorf("TimestampFromV1(%v) got %v, want %v", tt.u, got, tt.want)
		}
	}
}
<commit_msg>removed commented out test cases from testUUIDFormat()<commit_after>// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

package uuid

import (
	"bytes"
	"fmt"
	"testing"
	"time"
)

func TestUUID(t *testing.T) {
	t.Run("Bytes", testUUIDBytes)
	t.Run("String", testUUIDString)
	t.Run("Version", testUUIDVersion)
	t.Run("Variant", testUUIDVariant)
	t.Run("SetVersion", testUUIDSetVersion)
	t.Run("SetVariant", testUUIDSetVariant)
	t.Run("Format", testUUIDFormat)
}

func testUUIDBytes(t *testing.T) {
	got := codecTestUUID.Bytes()
	want := codecTestData
	if !bytes.Equal(got, want) {
		t.Errorf("%v.Bytes() = %x, want %x", codecTestUUID, got, want)
	}
}

func testUUIDString(t *testing.T) {
	got := NamespaceDNS.String()
	want := "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
	if got != want {
		t.Errorf("%v.String() = %q, want %q", NamespaceDNS, got, want)
	}
}

func testUUIDVersion(t *testing.T) {
	u := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
	if got, want := u.Version(), V1; got != want {
		t.Errorf("%v.Version() == %d, want %d", u, got, want)
	}
}

func testUUIDVariant(t *testing.T) {
	tests := []struct {
		u    UUID
		want byte
	}{
		{
			u:    UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
			want: VariantNCS,
		},
		{
			u:    UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
			want: VariantRFC4122,
		},
		{
			u:    UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
			want: VariantMicrosoft,
		},
		{
			u:    UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
			want: VariantFuture,
		},
	}
	for _, tt := range tests {
		if got := tt.u.Variant(); got != tt.want {
			t.Errorf("%v.Variant() == %d, want %d", tt.u, got, tt.want)
		}
	}
}

func testUUIDSetVersion(t *testing.T) {
	u := UUID{}
	want := V4
	u.SetVersion(want)
	if got := u.Version(); got != want {
		t.Errorf("%v.Version() == %d after SetVersion(%d)", u, got, want)
	}
}

func testUUIDSetVariant(t *testing.T) {
	variants := []byte{
		VariantNCS,
		VariantRFC4122,
		VariantMicrosoft,
		VariantFuture,
	}
	for _, want := range variants {
		u := UUID{}
		u.SetVariant(want)
		if got := u.Variant(); got != want {
			t.Errorf("%v.Variant() == %d after SetVariant(%d)", u, got, want)
		}
	}
}

func testUUIDFormat(t *testing.T) {
	val := Must(FromString("12345678-90ab-cdef-1234-567890abcdef"))
	tests := []struct {
		u    UUID
		f    string
		want string
	}{
		{u: val, f: "%s", want: "12345678-90ab-cdef-1234-567890abcdef"},
		{u: val, f: "%q", want: `"12345678-90ab-cdef-1234-567890abcdef"`},
		{u: val, f: "%x", want: "1234567890abcdef1234567890abcdef"},
		{u: val, f: "%X", want: "1234567890ABCDEF1234567890ABCDEF"},
		{u: val, f: "%v", want: "12345678-90ab-cdef-1234-567890abcdef"},
		{u: val, f: "%+v", want: "12345678-90ab-cdef-1234-567890abcdef"},
		{u: val, f: "%#v", want: "12345678-90ab-cdef-1234-567890abcdef"},
		{u: val, f: "%T", want: "uuid.UUID"},
		{u: val, f: "%t", want: ""},
		{u: val, f: "%b", want: ""},
		{u: val, f: "%c", want: ""},
		{u: val, f: "%d", want: ""},
		{u: val, f: "%e", want: ""},
		{u: val, f: "%E", want: ""},
		{u: val, f: "%f", want: ""},
		{u: val, f: "%F", want: ""},
		{u: val, f: "%g", want: ""},
		{u: val, f: "%G", want: ""},
		{u: val, f: "%o", want: ""},
		{u: val, f: "%U", want: ""},
	}
	for _, tt := range tests {
		got := fmt.Sprintf(tt.f, tt.u)
		if tt.want != got {
			t.Errorf("Format(\"%s\") got %s, want %s", tt.f, got, tt.want)
		}
	}
}

func TestMust(t *testing.T) {
	sentinel := fmt.Errorf("uuid: sentinel error")
	defer func() {
		r := recover()
		if r == nil {
			t.Fatalf("did not panic, want %v", sentinel)
		}
		err, ok := r.(error)
		if !ok {
			t.Fatalf("panicked with %T, want error (%v)", r, sentinel)
		}
		if err != sentinel {
			t.Fatalf("panicked with %v, want %v", err, sentinel)
		}
	}()
	fn := func() (UUID, error) {
		return Nil, sentinel
	}
	Must(fn())
}

func TestTimeFromTimestamp(t *testing.T) {
	tests := []struct {
		t    Timestamp
		want time.Time
	}{
		// a zero timestamp represents October 15, 1582 at midnight UTC
		{t: Timestamp(0), want: time.Date(1582, 10, 15, 0, 0, 0, 0, time.UTC)},
		// a one value is 100ns later
		{t: Timestamp(1), want: time.Date(1582, 10, 15, 0, 0, 0, 100, time.UTC)},
		// 10 million 100ns intervals later is one second
		{t: Timestamp(10000000), want: time.Date(1582, 10, 15, 0, 0, 1, 0, time.UTC)},
		{t: Timestamp(60 * 10000000), want: time.Date(1582, 10, 15, 0, 1, 0, 0, time.UTC)},
		{t: Timestamp(60 * 60 * 10000000), want: time.Date(1582, 10, 15, 1, 0, 0, 0, time.UTC)},
		{t: Timestamp(24 * 60 * 60 * 10000000), want: time.Date(1582, 10, 16, 0, 0, 0, 0, time.UTC)},
		{t: Timestamp(365 * 24 * 60 * 60 * 10000000), want: time.Date(1583, 10, 15, 0, 0, 0, 0, time.UTC)},
		// maximum timestamp value in a UUID is the year 5236
		{t: Timestamp(uint64(1<<60 - 1)), want: time.Date(5236, 03, 31, 21, 21, 0, 684697500, time.UTC)},
	}
	for _, tt := range tests {
		got, _ := tt.t.Time()
		if !got.Equal(tt.want) {
			t.Errorf("%v.Time() == %v, want %v", tt.t, got, tt.want)
		}
	}
}

func TestTimestampFromV1(t *testing.T) {
	tests := []struct {
		u       UUID
		want    Timestamp
		wanterr bool
	}{
		{u: Must(NewV4()), wanterr: true},
		{u: Must(FromString("00000000-0000-1000-0000-000000000000")), want: 0},
		{u: Must(FromString("424f137e-a2aa-11e8-98d0-529269fb1459")), want: 137538640775418750},
		{u: Must(FromString("ffffffff-ffff-1fff-ffff-ffffffffffff")), want: Timestamp(1<<60 - 1)},
	}
	for _, tt := range tests {
		got, goterr := TimestampFromV1(tt.u)
		if tt.wanterr && goterr == nil {
			t.Errorf("TimestampFromV1(%v) want error, got %v", tt.u, got)
		} else if tt.want != got {
			t.Errorf("TimestampFromV1(%v) got %v, want %v", tt.u, got, tt.want)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package main

import (
	"github.com/jacobsa/gcloud/gcs"

	"bazil.org/fuse"
)

type file struct {
	bucket     gcs.Bucket
	objectName string
	size       uint64
}

func (f *file) Attr() fuse.Attr {
	return fuse.Attr{
		// TODO(jacobsa): Expose ACLs from GCS?
		Mode: 0400,
		Size: f.size,
	}
}
<commit_msg>Added basic support for reading files.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"sync"

	"github.com/jacobsa/gcloud/gcs"
	"golang.org/x/net/context"

	"bazil.org/fuse"
	"bazil.org/fuse/fs"
)

// A remote object's name and metadata, along with a local temporary file that
// contains its contents (when initialized).
type file struct {
	bucket     gcs.Bucket
	objectName string
	size       uint64

	mu       sync.RWMutex
	tempFile *os.File // GUARDED_BY(mu)
}

// Make sure file implements the interfaces we think it does.
var (
	_ fs.Node           = &file{}
	_ fs.Handle         = &file{}
	_ fs.HandleReader   = &file{}
	_ fs.HandleReleaser = &file{}
)

func (f *file) Attr() fuse.Attr {
	return fuse.Attr{
		// TODO(jacobsa): Expose ACLs from GCS?
		Mode: 0400,
		Size: f.size,
	}
}

// If the file contents have not yet been fetched to a temporary file, fetch
// them.
func (f *file) ensureTempFile(ctx context.Context) error {
	f.mu.Lock()
	defer f.mu.Unlock()

	// Do we already have a file?
	if f.tempFile != nil {
		return nil
	}

	// Create a temporary file.
	tempFile, err := ioutil.TempFile("", "gcsfs")
	if err != nil {
		return fmt.Errorf("ioutil.TempFile: %v", err)
	}

	// Create a reader for the object.
	readCloser, err := f.bucket.NewReader(ctx, f.objectName)
	if err != nil {
		return fmt.Errorf("bucket.NewReader: %v", err)
	}

	defer readCloser.Close()

	// Copy the object contents into the file.
	if _, err := io.Copy(tempFile, readCloser); err != nil {
		return fmt.Errorf("io.Copy: %v", err)
	}

	// Save the file for later.
	f.tempFile = tempFile

	return nil
}

// Throw away the local temporary file, if any.
func (f *file) Release(ctx context.Context, req *fuse.ReleaseRequest) error {
	f.mu.Lock()
	defer f.mu.Unlock()

	// Is there a file to close?
	if f.tempFile == nil {
		return nil
	}

	// Close it, after grabbing its path.
	path := f.tempFile.Name()
	if err := f.tempFile.Close(); err != nil {
		log.Println("Error closing temp file:", err)
	}

	// Attempt to delete it.
	if err := os.Remove(path); err != nil {
		log.Println("Error deleting temp file:", err)
	}

	f.tempFile = nil
	return nil
}

// Ensure that the local temporary file is initialized, then read from it.
func (f *file) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
	// Ensure the temp file is present.
	if err := f.ensureTempFile(ctx); err != nil {
		return err
	}

	// Lock to read the temp file. If it went away in the meantime, that means
	// the kernel (erroneously) released us while reading from us.
	f.mu.RLock()
	defer f.mu.RUnlock()

	// Allocate a response buffer.
	resp.Data = make([]byte, req.Size)

	// Read the data.
	_, err := f.tempFile.ReadAt(resp.Data, req.Offset)

	return err
}
<|endoftext|>


<commit_before>package database

import (
	"encoding/json"
	"reflect"
	"strings"

	"github.com/pkg/errors"
)

const (
	CustomJSONOperationIDFollow = "follow"
)

var customJSONOpBodyObjects = map[string]interface{}{
	CustomJSONOperationIDFollow: &FollowOperation{},
}

// FC_REFLECT( steemit::chain::custom_json_operation,
//             (required_auths)
//             (required_posting_auths)
//             (id)
//             (json) )

type CustomJSONOperation struct {
	RequiredAuths        []string `json:"required_auths"`
	RequiredPostingAuths []string `json:"required_posting_auths"`
	ID                   string   `json:"id"`
	JSON                 string   `json:"json"`
}

func (op *CustomJSONOperation) UnmarshalBody() (interface{}, error) {
	// Get the corresponding operation object template.
	bodyTemplate, ok := customJSONOpBodyObjects[op.ID]
	if !ok {
		// In case there is no corresponding template, return unquoted data.
		return op.JSON, nil
	}

	// Clone the template.
	body := reflect.New(reflect.Indirect(reflect.ValueOf(bodyTemplate)).Type()).Interface()

	// Prepare the whole operation tuple.
	rawTuple := make([]json.RawMessage, 2)
	if err := json.NewDecoder(strings.NewReader(op.JSON)).Decode(&rawTuple); err != nil {
		return nil, errors.Wrapf(err, "failed to unmarshal CustomJSONOperation.JSON: \n%v", op.JSON)
	}
	if rawTuple[1] == nil {
		return nil, errors.Errorf("invalid CustomJSONOperation.JSON: \n%v", op.JSON)
	}
	data := []byte(rawTuple[1])

	// Unmarshal into the new object instance.
	if err := json.Unmarshal(data, body); err != nil {
		return nil, errors.Wrapf(err, "failed to unmarshal CustomJSONOperation.JSON: \n%v", op.JSON)
	}

	return body, nil
}

type FollowOperation struct {
	Follower  string   `json:"follower"`
	Following string   `json:"following"`
	What      []string `json:"what"`
}
<commit_msg>database: Fix custom_json unmarshalling, again<commit_after>package database

import (
	"bytes"
	"encoding/json"
	"io"
	"reflect"
	"strings"

	"github.com/pkg/errors"
)

const (
	CustomJSONOperationIDFollow = "follow"
)

var customJSONOpBodyObjects = map[string]interface{}{
	CustomJSONOperationIDFollow: &FollowOperation{},
}

// FC_REFLECT( steemit::chain::custom_json_operation,
//             (required_auths)
//             (required_posting_auths)
//             (id)
//             (json) )

type CustomJSONOperation struct {
	RequiredAuths        []string `json:"required_auths"`
	RequiredPostingAuths []string `json:"required_posting_auths"`
	ID                   string   `json:"id"`
	JSON                 string   `json:"json"`
}

func (op *CustomJSONOperation) UnmarshalBody() (interface{}, error) {
	// Get the corresponding operation object template.
	bodyTemplate, ok := customJSONOpBodyObjects[op.ID]
	if !ok {
		// In case there is no corresponding template, return unquoted data.
		return op.JSON, nil
	}

	// Clone the template.
	body := reflect.New(reflect.Indirect(reflect.ValueOf(bodyTemplate)).Type()).Interface()

	// Prepare the whole operation tuple.
	var bodyReader io.Reader
	if op.JSON[0] == '[' {
		rawTuple := make([]json.RawMessage, 2)
		if err := json.NewDecoder(strings.NewReader(op.JSON)).Decode(&rawTuple); err != nil {
			return nil, errors.Wrapf(err,
				"failed to unmarshal CustomJSONOperation.JSON: \n%v", op.JSON)
		}
		if rawTuple[1] == nil {
			return nil, errors.Errorf("invalid CustomJSONOperation.JSON: \n%v", op.JSON)
		}
		bodyReader = bytes.NewReader([]byte(rawTuple[1]))
	} else {
		bodyReader = strings.NewReader(op.JSON)
	}

	// Unmarshal into the new object instance.
	if err := json.NewDecoder(bodyReader).Decode(body); err != nil {
		return nil, errors.Wrapf(err,
			"failed to unmarshal CustomJSONOperation.JSON: \n%v", op.JSON)
	}

	return body, nil
}

type FollowOperation struct {
	Follower  string   `json:"follower"`
	Following string   `json:"following"`
	What      []string `json:"what"`
}
<|endoftext|>