<commit_before>package controllers

import (
	"fmt"
	"github.com/UniversityRadioYork/2016-site/models"
	"github.com/UniversityRadioYork/myradio-go"
	"log"
	"net"
	"net/http"

	"github.com/UniversityRadioYork/2016-site/structs"
	"github.com/UniversityRadioYork/2016-site/utils"
)

// NotFoundController is the controller for the 404 error page.
type NotFoundController struct {
	Controller
	shortURLs *models.ShortURLModel
}

// NewNotFoundController returns a new NotFoundController with the MyRadio
// session s and configuration context c.
func NewNotFoundController(s *myradio.Session, c *structs.Config) *NotFoundController {
	shorts := models.NewShortURLsModel(c, s)
	go shorts.UpdateTimer()
	return &NotFoundController{
		Controller: Controller{config: c},
		shortURLs:  shorts,
	}
}

// Get handles the HTTP GET request r for the 404 page, writing to w.
// It first checks if a short URL matches, in which case it redirects to it.
func (sc *NotFoundController) Get(w http.ResponseWriter, r *http.Request) {
	slug := r.URL.Path
	if slug[0] == '/' {
		slug = slug[1:]
	}
	if shortUrl := sc.shortURLs.Match(slug); shortUrl != nil {
		// Track the click asynchronously, for performance
		go func() {
			var reqIp net.IP
			var err error
			if reqIp, err = utils.GetRequesterIP(sc.config, r); err != nil {
				log.Println(fmt.Errorf("while getting requester IP: %w", err))
				return
			}
			if err = sc.shortURLs.TrackClick(
				shortUrl.ShortUrlID,
				r.Header.Get("User-Agent"),
				reqIp,
			); err != nil {
				log.Println(fmt.Errorf("while tracking short URL click: %w", err))
			}
		}()
		http.Redirect(w, r, shortUrl.RedirectTo, http.StatusTemporaryRedirect)
		return
	}
	w.WriteHeader(404)
	err := utils.RenderTemplate(w, sc.config.PageContext, nil, "404.tmpl")
	if err != nil {
		log.Println(err)
		return
	}
}
<commit_msg>whoops<commit_after>package controllers

import (
	"fmt"
	"github.com/UniversityRadioYork/2016-site/models"
	"github.com/UniversityRadioYork/myradio-go"
	"log"
	"net"
	"net/http"

	"github.com/UniversityRadioYork/2016-site/structs"
	"github.com/UniversityRadioYork/2016-site/utils"
)

// NotFoundController is the controller for the 404 error page.
type NotFoundController struct {
	Controller
	shortURLs *models.ShortURLModel
}

// NewNotFoundController returns a new NotFoundController with the MyRadio
// session s and configuration context c.
func NewNotFoundController(s *myradio.Session, c *structs.Config) *NotFoundController {
	shorts := models.NewShortURLsModel(c, s)
	go shorts.UpdateTimer()
	return &NotFoundController{
		Controller: Controller{config: c},
		shortURLs:  shorts,
	}
}

// Get handles the HTTP GET request r for the 404 page, writing to w.
// It first checks if a short URL matches, in which case it redirects to it.
func (sc *NotFoundController) Get(w http.ResponseWriter, r *http.Request) {
	slug := r.URL.Path
	if slug[0] == '/' {
		slug = slug[1:]
	}
	if shortUrl := sc.shortURLs.Match(slug); shortUrl != nil {
		// Track the click asynchronously, for performance
		go func() {
			var reqIp net.IP
			var err error
			if reqIp, err = utils.GetRequesterIP(sc.config, r); err != nil {
				log.Println(fmt.Errorf("while getting requester IP: %w", err))
				return
			}
			if err = sc.shortURLs.TrackClick(
				shortUrl.ShortURLID,
				r.Header.Get("User-Agent"),
				reqIp,
			); err != nil {
				log.Println(fmt.Errorf("while tracking short URL click: %w", err))
			}
		}()
		http.Redirect(w, r, shortUrl.RedirectTo, http.StatusTemporaryRedirect)
		return
	}
	w.WriteHeader(404)
	err := utils.RenderTemplate(w, sc.config.PageContext, nil, "404.tmpl")
	if err != nil {
		log.Println(err)
		return
	}
}
<|endoftext|>


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

Copyright (c) 2017 Thanh Ha

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.
*/

// lhc is a checker to find code files missing license headers.
package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"unicode"

	"github.com/zxiiro/license-header-checker/licenses"
)

var LICENSE_HEADER_LINES_MAX = 50
var VERSION = "0.1.0"

type License struct {
	Name string
	Text string
}

// Compare a license header with an approved list of license headers.
// Returns the name of the license that was approved. Else "".
func accepted_license(check string, approved []License) string {
	for _, i := range approved {
		if strings.Contains(check, i.Text) {
			return i.Name
		}
	}

	return ""
}

// check and exit if error.
func check(e error) {
	if e != nil {
		fmt.Println(e)
		os.Exit(1)
	}
}

func checkSPDX(license string, filename string) bool {
	file, err := os.Open(filename)
	check(err)
	defer file.Close()
	scanner := bufio.NewScanner(file)

	i := 0
	for scanner.Scan() {
		// Read only the first few lines to not read entire code file
		i++
		if i > LICENSE_HEADER_LINES_MAX {
			break
		}

		s := strings.ToUpper(scanner.Text())
		if strings.Contains(s, "SPDX-LICENSE-IDENTIFIER:") {
			spdx := stripSpaces(strings.SplitN(s, ":", 2)[1])
			if spdx == license {
				return true
			} else {
				return false
			}
		}
	}

	return false
}

func exclude(path string, excludes []string) bool {
	for i := range excludes {
		if strings.Contains(path, excludes[i]) {
			return true
		}
	}
	return false
}

func findFiles(directory string, patterns []string) []string {
	var files []string
	filepath.Walk(directory, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			for _, p := range patterns {
				f, _ := filepath.Glob(filepath.Join(path, p))
				files = append(files, f...)
			}
		}
		return nil
	})
	return files
}

// fetchLicense from file and return license text.
func fetchLicense(filename string) string {
	comment, multilineComment := false, false
	licenseText := ""

	var scanner *bufio.Scanner
	if filename == "Apache-2.0" {
		scanner = bufio.NewScanner(strings.NewReader(license.APACHE_20_LICENSE))
	} else if filename == "EPL-1.0" {
		scanner = bufio.NewScanner(strings.NewReader(license.EPL_10_LICENSE))
	} else if filename == "MIT" {
		scanner = bufio.NewScanner(strings.NewReader(license.MIT_LICENSE))
	} else {
		file, err := os.Open(filename)
		check(err)
		defer file.Close()

		// Read the first 2 bytes to decide if it is a comment string
		b := make([]byte, 2)
		_, err = file.Read(b)
		check(err)
		if isComment(string(b)) {
			comment = true
		}
		file.Seek(0, 0) // Reset so we can read the full file next

		scanner = bufio.NewScanner(file)
	}

	i := 0
	for scanner.Scan() {
		// Read only the first few lines to not read entire code file
		i++
		if i > LICENSE_HEADER_LINES_MAX {
			break
		}

		// We do not care about case sensitivity
		s := strings.ToUpper(scanner.Text())

		// Some projects DO NOT explicitly print this statement so ignore.
		s = strings.Replace(s, "ALL RIGHTS RESERVED.", "", -1)

		if ignoreComment(s) {
			continue
		}

		if comment == true {
			if strings.HasPrefix(s, "/*") {
				multilineComment = true
			} else if strings.Contains(s, "*/") {
				multilineComment = false
			}

			if !multilineComment && !isComment(s) ||
				// EPL headers can contain contributors list.
				strings.Contains(strings.ToUpper(s), " * CONTRIBUTORS:") {
				continue
			}

			s = trimComment(s)
		}

		licenseText += s
	}

	return stripSpaces(licenseText)
}

// Check if a string is a comment line.
func isComment(str string) bool {
	if !strings.HasPrefix(str, "#") &&
		!strings.HasPrefix(str, "//") &&
		!strings.HasPrefix(str, "/*") {
		return false
	}

	return true
}

// Ignore certain lines containing key strings
func ignoreComment(str string) bool {
	s := strings.ToUpper(str)
	if strings.HasPrefix(s, "#!") ||
		strings.Contains(s, "COPYRIGHT") ||
		strings.Contains(s, "SPDX-LICENSE-IDENTIFIER") ||
		// License name in LICENSE file but not header
		strings.Contains(s, "MIT LICENSE") {
		return true
	}

	return false
}

// Strip whitespace from string.
func stripSpaces(str string) string {
	return strings.Map(func(r rune) rune {
		if unicode.IsSpace(r) {
			return -1
		}
		return r
	}, str)
}

// Trim the comment prefix from string.
func trimComment(str string) string {
	str = strings.TrimLeft(str, "#")
	str = strings.TrimLeft(str, "//")
	str = strings.TrimLeft(str, "/*")
	str = strings.TrimLeft(str, " *")
	str = strings.Split(str, "*/")[0]
	str = strings.TrimLeft(str, "*")
	return str
}

// Usage prints a statement to explain how to use this command.
func usage() {
	fmt.Printf("Usage: %s [OPTIONS] [FILE]...\n", os.Args[0])
	fmt.Printf("Compare FILE with an expected license header.\n")
	fmt.Printf("\nOptions:\n")
	flag.PrintDefaults()
}

func main() {
	directoryPtr := flag.String("directory", ".",
		"Directory to search for files.")
	disableSPDXPtr := flag.Bool("disable-spdx", false,
		"Verify SDPX identifier matches license.")
	excludePtr := flag.String("exclude", "",
		"Comma-separated list of paths to exclude. The code will search for "+
			"paths containing this pattern. For example '/yang/gen/' is "+
			"'**/yang/gen/**'.")
	licensePtr := flag.String("license", "license.txt",
		"Comma-separated list of license files to compare against.")
	versionPtr := flag.Bool("version", false, "Print version")

	flag.Usage = usage
	flag.Parse()

	if *versionPtr {
		fmt.Println("License Checker version", VERSION)
		os.Exit(0)
	}

	fmt.Println("Search Patterns:", flag.Args())

	var accepted_licenses []License
	for _, l := range strings.Split(*licensePtr, ",") {
		license := License{l, fetchLicense(l)}
		accepted_licenses = append(accepted_licenses, license)
	}
	checkFiles := findFiles(*directoryPtr, flag.Args())

	ignore, miss, pass, spdx_miss, spdx_pass := 0, 0, 0, 0, 0
	for _, file := range checkFiles {

		if *excludePtr != "" && exclude(file, strings.Split(*excludePtr, ",")) {
			ignore++
			continue
		}

		headerText := fetchLicense(file)
		license := accepted_license(headerText, accepted_licenses)
		result := ""

		if license != "" {
			result = result + "✔"
			pass++
		} else {
			result = result + "✘"
			miss++
		}

		if !*disableSPDXPtr {
			if checkSPDX(license, file) {
				result = result + "✔"
				spdx_pass++
			} else {
				result = result + "✘"
				spdx_miss++
			}
		}
		fmt.Println(result, file)
	}

	fmt.Printf("License Total: %d, Ignored: %d, Missing: %d, Passed: %d\n",
		len(checkFiles), ignore, miss, pass)

	if !*disableSPDXPtr {
		fmt.Printf("SPDX Total: %d, Missing: %d, Passed: %d\n",
			len(checkFiles), spdx_miss, spdx_pass)
	}
}
<commit_msg>Update ignoreComment to check line prefixes<commit_after>/*
SPDX-License-Identifier: MIT

Copyright (c) 2017 Thanh Ha

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.
*/

// lhc is a checker to find code files missing license headers.
package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"unicode"

	"github.com/zxiiro/license-header-checker/licenses"
)

var LICENSE_HEADER_LINES_MAX = 50
var VERSION = "0.1.0"

type License struct {
	Name string
	Text string
}

// Compare a license header with an approved list of license headers.
// Returns the name of the license that was approved. Else "".
func accepted_license(check string, approved []License) string {
	for _, i := range approved {
		if strings.Contains(check, i.Text) {
			return i.Name
		}
	}

	return ""
}

// check and exit if error.
func check(e error) {
	if e != nil {
		fmt.Println(e)
		os.Exit(1)
	}
}

func checkSPDX(license string, filename string) bool {
	file, err := os.Open(filename)
	check(err)
	defer file.Close()
	scanner := bufio.NewScanner(file)

	i := 0
	for scanner.Scan() {
		// Read only the first few lines to not read entire code file
		i++
		if i > LICENSE_HEADER_LINES_MAX {
			break
		}

		s := strings.ToUpper(scanner.Text())
		if strings.Contains(s, "SPDX-LICENSE-IDENTIFIER:") {
			spdx := stripSpaces(strings.SplitN(s, ":", 2)[1])
			if spdx == license {
				return true
			} else {
				return false
			}
		}
	}

	return false
}

func exclude(path string, excludes []string) bool {
	for i := range excludes {
		if strings.Contains(path, excludes[i]) {
			return true
		}
	}
	return false
}

func findFiles(directory string, patterns []string) []string {
	var files []string
	filepath.Walk(directory, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			for _, p := range patterns {
				f, _ := filepath.Glob(filepath.Join(path, p))
				files = append(files, f...)
			}
		}
		return nil
	})
	return files
}

// fetchLicense from file and return license text.
func fetchLicense(filename string) string {
	comment, multilineComment := false, false
	licenseText := ""

	var scanner *bufio.Scanner
	if filename == "Apache-2.0" {
		scanner = bufio.NewScanner(strings.NewReader(license.APACHE_20_LICENSE))
	} else if filename == "EPL-1.0" {
		scanner = bufio.NewScanner(strings.NewReader(license.EPL_10_LICENSE))
	} else if filename == "MIT" {
		scanner = bufio.NewScanner(strings.NewReader(license.MIT_LICENSE))
	} else {
		file, err := os.Open(filename)
		check(err)
		defer file.Close()

		// Read the first 2 bytes to decide if it is a comment string
		b := make([]byte, 2)
		_, err = file.Read(b)
		check(err)
		if isComment(string(b)) {
			comment = true
		}
		file.Seek(0, 0) // Reset so we can read the full file next

		scanner = bufio.NewScanner(file)
	}

	i := 0
	for scanner.Scan() {
		// Read only the first few lines to not read entire code file
		i++
		if i > LICENSE_HEADER_LINES_MAX {
			break
		}

		// We do not care about case sensitivity
		s := strings.ToUpper(scanner.Text())

		// Some projects DO NOT explicitly print this statement so ignore.
		s = strings.Replace(s, "ALL RIGHTS RESERVED.", "", -1)

		if ignoreComment(s) {
			continue
		}

		if comment == true {
			if strings.HasPrefix(s, "/*") {
				multilineComment = true
			} else if strings.Contains(s, "*/") {
				multilineComment = false
			}

			if !multilineComment && !isComment(s) ||
				// EPL headers can contain contributors list.
				strings.Contains(strings.ToUpper(s), " * CONTRIBUTORS:") {
				continue
			}

			s = trimComment(s)
		}

		licenseText += s
	}

	return stripSpaces(licenseText)
}

// Check if a string is a comment line.
func isComment(str string) bool {
	if !strings.HasPrefix(str, "#") &&
		!strings.HasPrefix(str, "//") &&
		!strings.HasPrefix(str, "/*") {
		return false
	}

	return true
}

// Ignore certain lines containing key strings
func ignoreComment(str string) bool {
	s := strings.ToUpper(trimComment(str))
	if strings.HasPrefix(s, "#!") ||
		strings.HasPrefix(s, "COPYRIGHT") ||
		strings.HasPrefix(s, "SPDX-LICENSE-IDENTIFIER") ||
		// License name in LICENSE file but not header
		strings.HasPrefix(s, "MIT LICENSE") {
		return true
	}

	return false
}

// Strip whitespace from string.
func stripSpaces(str string) string {
	return strings.Map(func(r rune) rune {
		if unicode.IsSpace(r) {
			return -1
		}
		return r
	}, str)
}

// Trim the comment prefix from string.
func trimComment(str string) string {
	str = strings.TrimLeft(str, "#")
	str = strings.TrimLeft(str, "//")
	str = strings.TrimLeft(str, "/*")
	str = strings.TrimLeft(str, " *")
	str = strings.Split(str, "*/")[0]
	str = strings.TrimLeft(str, "*")
	return str
}

// Usage prints a statement to explain how to use this command.
func usage() {
	fmt.Printf("Usage: %s [OPTIONS] [FILE]...\n", os.Args[0])
	fmt.Printf("Compare FILE with an expected license header.\n")
	fmt.Printf("\nOptions:\n")
	flag.PrintDefaults()
}

func main() {
	directoryPtr := flag.String("directory", ".",
		"Directory to search for files.")
	disableSPDXPtr := flag.Bool("disable-spdx", false,
		"Verify SDPX identifier matches license.")
	excludePtr := flag.String("exclude", "",
		"Comma-separated list of paths to exclude. The code will search for "+
			"paths containing this pattern. For example '/yang/gen/' is "+
			"'**/yang/gen/**'.")
	licensePtr := flag.String("license", "license.txt",
		"Comma-separated list of license files to compare against.")
	versionPtr := flag.Bool("version", false, "Print version")

	flag.Usage = usage
	flag.Parse()

	if *versionPtr {
		fmt.Println("License Checker version", VERSION)
		os.Exit(0)
	}

	fmt.Println("Search Patterns:", flag.Args())

	var accepted_licenses []License
	for _, l := range strings.Split(*licensePtr, ",") {
		license := License{l, fetchLicense(l)}
		accepted_licenses = append(accepted_licenses, license)
	}
	checkFiles := findFiles(*directoryPtr, flag.Args())

	ignore, miss, pass, spdx_miss, spdx_pass := 0, 0, 0, 0, 0
	for _, file := range checkFiles {

		if *excludePtr != "" && exclude(file, strings.Split(*excludePtr, ",")) {
			ignore++
			continue
		}

		headerText := fetchLicense(file)
		license := accepted_license(headerText, accepted_licenses)
		result := ""

		if license != "" {
			result = result + "✔"
			pass++
		} else {
			result = result + "✘"
			miss++
		}

		if !*disableSPDXPtr {
			if checkSPDX(license, file) {
				result = result + "✔"
				spdx_pass++
			} else {
				result = result + "✘"
				spdx_miss++
			}
		}
		fmt.Println(result, file)
	}

	fmt.Printf("License Total: %d, Ignored: %d, Missing: %d, Passed: %d\n",
		len(checkFiles), ignore, miss, pass)

	if !*disableSPDXPtr {
		fmt.Printf("SPDX Total: %d, Missing: %d, Passed: %d\n",
			len(checkFiles), spdx_miss, spdx_pass)
	}
}
<|endoftext|>


<commit_before>package main

import (
  "compress/gzip"
  "database/sql"
  "encoding/csv"
  "flag"
  "fmt"
  "io"
  "os"
  _ "github.com/go-sql-driver/mysql"
)

// Queryable interface that matches sql.DB and sql.Tx.
type queryable interface {
  Query(query string, args ...interface{}) (*sql.Rows, error)
}

func dump(tables []string, db queryable, outputDir string, compressOut bool) error {
  for _, table := range tables {
    err := dumpTable(table, db, outputDir, compressOut)
    if err != nil {
      fmt.Printf("Error dumping %s: %s\n", table, err)
    }
  }
  return nil
}

func dumpTable(table string, db queryable, outputDir string, compressOut bool) error {
  fname := outputDir + "/" + table + ".csv"
  if compressOut {
    fname = fname + ".gz"
  }

  f, err := os.Create(fname)
  if err != nil {
    return err
  }
  defer f.Close()

  var out io.Writer
  if compressOut {
    gzout := gzip.NewWriter(f)
    defer gzout.Close()
    out = gzout
  } else {
    out = f
  }

  w := csv.NewWriter(out)

  rows, err := db.Query("SELECT * FROM " + table)   // Couldn't get placeholder expansion to work here
  if err != nil {
    return err
  }

  columns, err := rows.Columns()
  if err != nil {
    panic(err.Error())
  }
  err = w.Write(columns)   // Header
  if err != nil {
    return err
  }

  for rows.Next() {
    // Shamelessly ripped (and modified) from http://play.golang.org/p/jxza3pbqq9

    // Create interface set
    values := make([]interface{}, len(columns))
    scanArgs := make([]interface{}, len(values))
    for i := range values {
      scanArgs[i] = &values[i]
    }

    // Scan for arbitrary values
    err = rows.Scan(scanArgs...)
    if err != nil {
      return err
    }

    // Print data
    csvData := make([]string, 0, len(values))
    for _, value := range values {
      switch value.(type) {
      default:
        s := fmt.Sprintf("%s", value)
        csvData = append(csvData, string(s))
      }
    }
    err = w.Write(csvData)
    if err != nil {
      return err
    }
  }

  w.Flush()
  err = w.Error()
  if err != nil {
    return err
  }

  return nil
}

func getTables(db queryable) ([]string, error) {
  tables := make([]string, 0, 10)
  rows, err := db.Query("SHOW TABLES")
  if err != nil {
    return nil, err
  }
  for rows.Next() {
    var table string
    rows.Scan(&table)
    tables = append(tables, table)
  }
  return tables, nil
}

func main() {
  dbUser := flag.String("user", "root", "database user")
  dbPassword := flag.String("password", "", "database password")
  dbHost := flag.String("hostname", "", "database host")
  dbPort := flag.Int("port", 3306, "database port")
  outputDir := flag.String("outdir", "", "where output will be stored")
  //csvSep := flag.String("fields-terminated-by", "\t", "character to terminate fields by")
  //csvOptEncloser := flag.String("fields-optionally-enclosed-by", "\"", "character to enclose fields with when needed")
  //csvEscape := flag.String("fields-escaped-by", "\\", "character to escape special characters with")
  //compressCon := flag.Bool("compress-con", false, "whether compress connection or not")
  compressFiles := flag.Bool("compress-file", false, "whether compress connection or not")
  useTransaction := flag.Bool("single-transaction", true, "whether to wrap everything in a transaction or not.")

  flag.Parse()
  args := flag.Args()
  if len(args) < 1 {
    fmt.Println("Database name must be defined.")
    flag.PrintDefaults()
    os.Exit(1)
  }
  dbName := args[0]

  dbUrl := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", *dbUser, *dbPassword, *dbHost, *dbPort, dbName)
  //fmt.Println("DB url:", dbUrl)
  db, err := sql.Open("mysql", dbUrl)
  if err != nil {
    fmt.Fprintf(os.Stderr, "Could not connect to server: %s\n", err)
  }
  defer db.Close()

  var q queryable
  if *useTransaction {
    tx, err := db.Begin()
    if err != nil {
      panic(err)
    }
    defer tx.Rollback()
    q = tx
  } else {
    q = db
  }

  var tables []string
  if len(args) > 1 {
    tables = args[1:]
  } else {
    tables, err = getTables(q)
  }

  err = dump(tables, q, *outputDir, *compressFiles)
  if err != nil {
    panic(err)
  }
}
<commit_msg>feat: option to skip header in csv<commit_after>package main

import (
  "compress/gzip"
  "database/sql"
  "encoding/csv"
  "flag"
  "fmt"
  "io"
  "os"
  _ "github.com/go-sql-driver/mysql"
)

// Queryable interface that matches sql.DB and sql.Tx.
type queryable interface {
  Query(query string, args ...interface{}) (*sql.Rows, error)
}

func dump(tables []string, db queryable, outputDir string, compressOut bool, skipHeader bool) error {
  for _, table := range tables {
    err := dumpTable(table, db, outputDir, compressOut, skipHeader)
    if err != nil {
      fmt.Printf("Error dumping %s: %s\n", table, err)
    }
  }
  return nil
}

func dumpTable(table string, db queryable, outputDir string, compressOut bool, skipHeader bool) error {
  fname := outputDir + "/" + table + ".csv"
  if compressOut {
    fname = fname + ".gz"
  }

  f, err := os.Create(fname)
  if err != nil {
    return err
  }
  defer f.Close()

  var out io.Writer
  if compressOut {
    gzout := gzip.NewWriter(f)
    defer gzout.Close()
    out = gzout
  } else {
    out = f
  }

  w := csv.NewWriter(out)

  rows, err := db.Query("SELECT * FROM " + table)   // Couldn't get placeholder expansion to work here
  if err != nil {
    return err
  }

  columns, err := rows.Columns()
  if err != nil {
    panic(err.Error())
  }
  if (!skipHeader) {
    err = w.Write(columns)   // Header
    if err != nil {
      return err
    }
  }

  for rows.Next() {
    // Shamelessly ripped (and modified) from http://play.golang.org/p/jxza3pbqq9

    // Create interface set
    values := make([]interface{}, len(columns))
    scanArgs := make([]interface{}, len(values))
    for i := range values {
      scanArgs[i] = &values[i]
    }

    // Scan for arbitrary values
    err = rows.Scan(scanArgs...)
    if err != nil {
      return err
    }

    // Print data
    csvData := make([]string, 0, len(values))
    for _, value := range values {
      switch value.(type) {
      default:
        s := fmt.Sprintf("%s", value)
        csvData = append(csvData, string(s))
      }
    }
    err = w.Write(csvData)
    if err != nil {
      return err
    }
  }

  w.Flush()
  err = w.Error()
  if err != nil {
    return err
  }

  return nil
}

func getTables(db queryable) ([]string, error) {
  tables := make([]string, 0, 10)
  rows, err := db.Query("SHOW TABLES")
  if err != nil {
    return nil, err
  }
  for rows.Next() {
    var table string
    rows.Scan(&table)
    tables = append(tables, table)
  }
  return tables, nil
}

func main() {
  dbUser := flag.String("user", "root", "database user")
  dbPassword := flag.String("password", "", "database password")
  dbHost := flag.String("hostname", "", "database host")
  dbPort := flag.Int("port", 3306, "database port")
  outputDir := flag.String("outdir", "", "where output will be stored")
  //csvSep := flag.String("fields-terminated-by", "\t", "character to terminate fields by")
  //csvOptEncloser := flag.String("fields-optionally-enclosed-by", "\"", "character to enclose fields with when needed")
  //csvEscape := flag.String("fields-escaped-by", "\\", "character to escape special characters with")
  //compressCon := flag.Bool("compress-con", false, "whether compress connection or not")
  compressFiles := flag.Bool("compress-file", false, "whether compress connection or not")
  useTransaction := flag.Bool("single-transaction", true, "whether to wrap everything in a transaction or not.")
  skipHeader := flag.Bool("skip-header", false, "whether column header should be included or not")

  flag.Parse()
  args := flag.Args()
  if len(args) < 1 {
    fmt.Println("Database name must be defined.")
    flag.PrintDefaults()
    os.Exit(1)
  }
  dbName := args[0]

  dbUrl := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", *dbUser, *dbPassword, *dbHost, *dbPort, dbName)
  //fmt.Println("DB url:", dbUrl)
  db, err := sql.Open("mysql", dbUrl)
  if err != nil {
    fmt.Fprintf(os.Stderr, "Could not connect to server: %s\n", err)
  }
  defer db.Close()

  var q queryable
  if *useTransaction {
    tx, err := db.Begin()
    if err != nil {
      panic(err)
    }
    defer tx.Rollback()
    q = tx
  } else {
    q = db
  }

  var tables []string
  if len(args) > 1 {
    tables = args[1:]
  } else {
    tables, err = getTables(q)
  }

  err = dump(tables, q, *outputDir, *compressFiles, *skipHeader)
  if err != nil {
    panic(err)
  }
}
<|endoftext|>


<commit_before>package rc4

// #cgo LDFLAGS: -lcrypto
// #include <openssl/rc4.h>

import "C"

import (
	"strconv"
)

type Cipher struct {
	key *_Ctype_RC4_KEY
}

type KeySizeError int

func (k KeySizeError) Error() string {
	return "rc4: invalid key size " + strconv.Itoa(int(k))
}

func NewCipher(key []byte) (*Cipher, error) {
	k := len(key)
	if k < 1 || k > 256 {
		return nil, KeySizeError(k)
	}
	var c Cipher
	c.key = &_Ctype_RC4_KEY{}
	C.RC4_set_key(c.key, C.int(k), (*_Ctype_unsignedchar)(&key[0]))

	return &c, nil
}

func (c *Cipher) XORKeyStream(dst, src []byte) {
	C.RC4(c.key, C.size_t(len(dst)), (*_Ctype_unsignedchar)(&src[0]),
		(*_Ctype_unsignedchar)(&dst[0]))
}

func (c *Cipher) Reset() {
	for i := 0; i < 256; i++ {
		c.key.data[i] = 0
	}
	c.key.x = 0
	c.key.y = 0
}
<commit_msg>Remove blank line that breaks cgo<commit_after>package rc4

// #cgo LDFLAGS: -lcrypto
// #include <openssl/rc4.h>
import "C"

import (
	"strconv"
)

type Cipher struct {
	key *_Ctype_RC4_KEY
}

type KeySizeError int

func (k KeySizeError) Error() string {
	return "rc4: invalid key size " + strconv.Itoa(int(k))
}

func NewCipher(key []byte) (*Cipher, error) {
	k := len(key)
	if k < 1 || k > 256 {
		return nil, KeySizeError(k)
	}
	var c Cipher
	c.key = &_Ctype_RC4_KEY{}
	C.RC4_set_key(c.key, C.int(k), (*_Ctype_unsignedchar)(&key[0]))

	return &c, nil
}

func (c *Cipher) XORKeyStream(dst, src []byte) {
	C.RC4(c.key, C.size_t(len(dst)), (*_Ctype_unsignedchar)(&src[0]),
		(*_Ctype_unsignedchar)(&dst[0]))
}

func (c *Cipher) Reset() {
	for i := 0; i < 256; i++ {
		c.key.data[i] = 0
	}
	c.key.x = 0
	c.key.y = 0
}
<|endoftext|>


<commit_before>// Copyright 2015 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 oglematchers_test

import (
	"testing"

	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

func TestHasSameTypeAs(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type HasSameTypeAsTest struct {
}

func init() { RegisterTestSuite(&HasSameTypeAsTest{}) }

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *HasSameTypeAsTest) CandidateIsLiteralNil() {
	matcher := HasSameTypeAs(nil)
	var err error

	// Description
	ExpectEq("has type <nil>", matcher.Description())

	// Literal nil
	err = matcher.Matches(nil)
	ExpectEq(nil, err)

	// int
	err = matcher.Matches(17)
	AssertNe(nil, err)
	ExpectThat(err, Error(Equals("which has type int")))

	// string
	err = matcher.Matches("")
	AssertNe(nil, err)
	ExpectThat(err, Error(Equals("which has type string")))

	// nil map
	var m map[string]string
	err = matcher.Matches(m)

	AssertNe(nil, err)
	ExpectThat(err, Error(Equals("which has type map[string]string")))

	// Non-nil map
	m = make(map[string]string)
	err = matcher.Matches(m)

	AssertNe(nil, err)
	ExpectThat(err, Error(Equals("which has type map[string]string")))
}

func (t *HasSameTypeAsTest) CandidateIsNilMap() {
	var m map[string]string
	matcher := HasSameTypeAs(m)
	var err error

	// Description
	ExpectEq("has type map[string]string", matcher.Description())

	// nil map
	m = nil
	err = matcher.Matches(m)
	ExpectEq(nil, err)

	// Non-nil map
	m = make(map[string]string)
	err = matcher.Matches(m)
	ExpectEq(nil, err)

	// Literal nil
	err = matcher.Matches(nil)
	AssertNe(nil, err)
	ExpectThat(err, Error(Equals("which has type <nil>")))

	// int
	err = matcher.Matches(17)
	AssertNe(nil, err)
	ExpectThat(err, Error(Equals("which has type int")))

	// string
	err = matcher.Matches("")
	AssertNe(nil, err)
	ExpectThat(err, Error(Equals("which has type string")))
}

func (t *HasSameTypeAsTest) CandidateIsNilInterface() {
	AssertTrue(false, "TODO")
}

func (t *HasSameTypeAsTest) CandidateIsString() {
	AssertTrue(false, "TODO")
}

func (t *HasSameTypeAsTest) CandidateIsStringAlias() {
	AssertTrue(false, "TODO")
}
<commit_msg>HasSameTypeAsTest.CandidateIsNilInInterfaceVariable<commit_after>// Copyright 2015 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 oglematchers_test

import (
	"io"
	"testing"

	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

func TestHasSameTypeAs(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type HasSameTypeAsTest struct {
}

func init() { RegisterTestSuite(&HasSameTypeAsTest{}) }

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *HasSameTypeAsTest) CandidateIsLiteralNil() {
	matcher := HasSameTypeAs(nil)
	var err error

	// Description
	ExpectEq("has type <nil>", matcher.Description())

	// Literal nil
	err = matcher.Matches(nil)
	ExpectEq(nil, err)

	// nil in interface variable
	var r io.Reader
	err = matcher.Matches(r)
	ExpectEq(nil, err)

	// int
	err = matcher.Matches(17)
	AssertNe(nil, err)
	ExpectThat(err, Error(Equals("which has type int")))

	// string
	err = matcher.Matches("")
	AssertNe(nil, err)
	ExpectThat(err, Error(Equals("which has type string")))

	// nil map
	var m map[string]string
	err = matcher.Matches(m)

	AssertNe(nil, err)
	ExpectThat(err, Error(Equals("which has type map[string]string")))

	// Non-nil map
	m = make(map[string]string)
	err = matcher.Matches(m)

	AssertNe(nil, err)
	ExpectThat(err, Error(Equals("which has type map[string]string")))
}

func (t *HasSameTypeAsTest) CandidateIsNilMap() {
	var m map[string]string
	matcher := HasSameTypeAs(m)
	var err error

	// Description
	ExpectEq("has type map[string]string", matcher.Description())

	// nil map
	m = nil
	err = matcher.Matches(m)
	ExpectEq(nil, err)

	// Non-nil map
	m = make(map[string]string)
	err = matcher.Matches(m)
	ExpectEq(nil, err)

	// Literal nil
	err = matcher.Matches(nil)
	AssertNe(nil, err)
	ExpectThat(err, Error(Equals("which has type <nil>")))

	// int
	err = matcher.Matches(17)
	AssertNe(nil, err)
	ExpectThat(err, Error(Equals("which has type int")))

	// string
	err = matcher.Matches("")
	AssertNe(nil, err)
	ExpectThat(err, Error(Equals("which has type string")))
}

func (t *HasSameTypeAsTest) CandidateIsNilInInterfaceVariable() {
	var r io.Reader
	matcher := HasSameTypeAs(r)
	var err error

	// Description
	ExpectEq("has type <nil>", matcher.Description())

	// nil in interface variable
	r = nil
	err = matcher.Matches(r)
	ExpectEq(nil, err)

	// Literal nil
	err = matcher.Matches(nil)
	ExpectEq(nil, err)

	// int
	err = matcher.Matches(17)
	AssertNe(nil, err)
	ExpectThat(err, Error(Equals("which has type int")))
}

func (t *HasSameTypeAsTest) CandidateIsString() {
	AssertTrue(false, "TODO")
}

func (t *HasSameTypeAsTest) CandidateIsStringAlias() {
	AssertTrue(false, "TODO")
}
<|endoftext|>


<commit_before>// Copyright 2013 Mark Canning
//
// 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.
//
//
// Author: Mark Canning
// Developed at: Tamber, Inc. (http://www.tamber.com/).
//
// Tamber also has this really cool recommendation engine for music
// (also development by me) which prioritizes up-and-coming artists, so
// it doesn't succomb to the popularity biases that plague modern
// recommendation engines, and still produces excellent personalized
// recommendations! Make sure to check us out at http://www.tamber.com
// or https://itunes.apple.com/us/app/tamber-concerts/id658240483

package main

import (
	"bytes"
	"fmt"
	"github.com/argusdusty/Ferret"
	"io/ioutil"
	"strconv"
	"time"
)

var Correction = func(b []byte) [][]byte { return ferret.ErrorCorrect(b, ferret.LowercaseLetters) }
var LengthSorter = func(s string, v interface{}, l int, i int) float64 { return -float64(l + i) }
var FreqSorter = func(s string, v interface{}, l int, i int) float64 { return float64(v.(uint64)) }
var Converter = ferret.UnicodeToLowerASCII

func main() {
	t := time.Now()
	Data, err := ioutil.ReadFile("dictionary.dat")
	if err != nil {
		panic(err)
	}
	Words := make([]string, 0)
	Values := make([]interface{}, 0)
	for _, Vals := range bytes.Split(Data, []byte("\r\n")) {
		WordFreq := bytes.Split(Vals, []byte(" "))
		if len(WordFreq) != 2 {
			continue
		}
		Freq, err := strconv.ParseUint(string(WordFreq[1]), 10, 64)
		if err != nil {
			continue
		}
		Words = append(Words, string(WordFreq[0]))
		Values = append(Values, Freq)
	}
	fmt.Println("Loaded dictionary in:", time.Now().Sub(t))
	t = time.Now()

	SearchEngine := ferret.New(Words, Words, Values, Converter)
	fmt.Println("Created index in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.Query("ar", 5))
	fmt.Println("Performed search in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.Query("test", 5))
	fmt.Println("Performed search in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.ErrorCorrectingQuery("tsst", 5, Correction))
	fmt.Println("Performed error correcting search in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.SortedErrorCorrectingQuery("tssst", 5, Correction, LengthSorter))
	fmt.Println("Performed sorted error correcting search in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.SortedErrorCorrectingQuery("tssst", 5, Correction, FreqSorter))
	fmt.Println("Performed sorted error correcting search in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.SortedQuery("a", 5, LengthSorter))
	fmt.Println("Performed sorted search in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.SortedQuery("a", 5, FreqSorter))
	fmt.Println("Performed sorted search in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.Query("a", 5))
	fmt.Println("Performed search in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.Query("the", 25))
	fmt.Println("Performed search in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.SortedQuery("the", 25, FreqSorter))
	fmt.Println("Performed sorted search in:", time.Now().Sub(t))
	t = time.Now()
	SearchEngine.Insert("asdfghjklqwertyuiopzxcvbnm", "asdfghjklqwertyuiopzxcvbnm", uint64(0))
	fmt.Println("Performed insert in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.Query("sdfghjklqwert", 5))
	fmt.Println("Performed search in:", time.Now().Sub(t))
	fmt.Println("Running benchmarks...")
	t = time.Now()
	n := 0
	for _, Query := range SearchEngine.Words {
		SearchEngine.Query(string(Query), 5)
		n++
	}
	fmt.Println("Performed", n, "limit-5 searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words {
		SearchEngine.Query(string(Query), 25)
		n++
	}
	fmt.Println("Performed", n, "limit-25 searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words {
		SearchEngine.SortedQuery(string(Query), 5, LengthSorter)
		n++
	}
	fmt.Println("Performed", n, "limit-5 length sorted searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words {
		SearchEngine.SortedQuery(string(Query), 25, LengthSorter)
		n++
	}
	fmt.Println("Performed", n, "limit-25 length sorted searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words {
		SearchEngine.SortedQuery(string(Query), 5, FreqSorter)
		n++
	}
	fmt.Println("Performed", n, "limit-5 frequency sorted searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words {
		SearchEngine.SortedQuery(string(Query), 25, FreqSorter)
		n++
	}
	fmt.Println("Performed", n, "limit-25 frequency sorted searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words[:2048] {
		SearchEngine.ErrorCorrectingQuery(string(Query)+"0", 5, Correction)
		n++
	}
	fmt.Println("Performed", n, "limit-5 error correcting searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words[:2048] {
		SearchEngine.ErrorCorrectingQuery(string(Query)+"0", 25, Correction)
		n++
	}
	fmt.Println("Performed", n, "limit-25 error correcting searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words[:2048] {
		SearchEngine.SortedErrorCorrectingQuery(string(Query)+"0", 5, Correction, LengthSorter)
		n++
	}
	fmt.Println("Performed", n, "limit-5 length sorted error correcting searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words[:2048] {
		SearchEngine.SortedErrorCorrectingQuery(string(Query)+"0", 25, Correction, LengthSorter)
		n++
	}
	fmt.Println("Performed", n, "limit-25 length sorted error correcting searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words[:2048] {
		SearchEngine.SortedErrorCorrectingQuery(string(Query)+"0", 5, Correction, FreqSorter)
		n++
	}
	fmt.Println("Performed", n, "limit-5 frequency sorted error correcting searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words[:2048] {
		SearchEngine.SortedErrorCorrectingQuery(string(Query)+"0", 25, Correction, FreqSorter)
		n++
	}
	fmt.Println("Performed", n, "limit-25 frequency sorted error correcting searches in:", time.Now().Sub(t))
}
<commit_msg>dictionaryexample line endings fix issue #7<commit_after>// Copyright 2013 Mark Canning
//
// 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.
//
//
// Author: Mark Canning
// Developed at: Tamber, Inc. (http://www.tamber.com/).
//
// Tamber also has this really cool recommendation engine for music
// (also development by me) which prioritizes up-and-coming artists, so
// it doesn't succomb to the popularity biases that plague modern
// recommendation engines, and still produces excellent personalized
// recommendations! Make sure to check us out at http://www.tamber.com
// or https://itunes.apple.com/us/app/tamber-concerts/id658240483

package main

import (
	"bytes"
	"fmt"
	"github.com/argusdusty/Ferret"
	"io/ioutil"
	"strconv"
	"time"
)

var Correction = func(b []byte) [][]byte { return ferret.ErrorCorrect(b, ferret.LowercaseLetters) }
var LengthSorter = func(s string, v interface{}, l int, i int) float64 { return -float64(l + i) }
var FreqSorter = func(s string, v interface{}, l int, i int) float64 { return float64(v.(uint64)) }
var Converter = ferret.UnicodeToLowerASCII

func main() {
	t := time.Now()
	Data, err := ioutil.ReadFile("dictionary.dat")
	if err != nil {
		panic(err)
	}
	Words := make([]string, 0)
	Values := make([]interface{}, 0)
	for _, Vals := range bytes.Split(Data, []byte("\n")) {
		Vals = bytes.TrimSpace(Vals)
		WordFreq := bytes.Split(Vals, []byte(" "))
		if len(WordFreq) != 2 {
			continue
		}
		Freq, err := strconv.ParseUint(string(WordFreq[1]), 10, 64)
		if err != nil {
			continue
		}
		Words = append(Words, string(WordFreq[0]))
		Values = append(Values, Freq)
	}
	fmt.Println("Loaded dictionary in:", time.Now().Sub(t))
	t = time.Now()

	SearchEngine := ferret.New(Words, Words, Values, Converter)
	fmt.Println("Created index in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.Query("ar", 5))
	fmt.Println("Performed search in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.Query("test", 5))
	fmt.Println("Performed search in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.ErrorCorrectingQuery("tsst", 5, Correction))
	fmt.Println("Performed error correcting search in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.SortedErrorCorrectingQuery("tssst", 5, Correction, LengthSorter))
	fmt.Println("Performed sorted error correcting search in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.SortedErrorCorrectingQuery("tssst", 5, Correction, FreqSorter))
	fmt.Println("Performed sorted error correcting search in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.SortedQuery("a", 5, LengthSorter))
	fmt.Println("Performed sorted search in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.SortedQuery("a", 5, FreqSorter))
	fmt.Println("Performed sorted search in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.Query("a", 5))
	fmt.Println("Performed search in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.Query("the", 25))
	fmt.Println("Performed search in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.SortedQuery("the", 25, FreqSorter))
	fmt.Println("Performed sorted search in:", time.Now().Sub(t))
	t = time.Now()
	SearchEngine.Insert("asdfghjklqwertyuiopzxcvbnm", "asdfghjklqwertyuiopzxcvbnm", uint64(0))
	fmt.Println("Performed insert in:", time.Now().Sub(t))
	t = time.Now()
	fmt.Println(SearchEngine.Query("sdfghjklqwert", 5))
	fmt.Println("Performed search in:", time.Now().Sub(t))
	fmt.Println("Running benchmarks...")
	t = time.Now()
	n := 0
	for _, Query := range SearchEngine.Words {
		SearchEngine.Query(string(Query), 5)
		n++
	}
	fmt.Println("Performed", n, "limit-5 searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words {
		SearchEngine.Query(string(Query), 25)
		n++
	}
	fmt.Println("Performed", n, "limit-25 searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words {
		SearchEngine.SortedQuery(string(Query), 5, LengthSorter)
		n++
	}
	fmt.Println("Performed", n, "limit-5 length sorted searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words {
		SearchEngine.SortedQuery(string(Query), 25, LengthSorter)
		n++
	}
	fmt.Println("Performed", n, "limit-25 length sorted searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words {
		SearchEngine.SortedQuery(string(Query), 5, FreqSorter)
		n++
	}
	fmt.Println("Performed", n, "limit-5 frequency sorted searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words {
		SearchEngine.SortedQuery(string(Query), 25, FreqSorter)
		n++
	}
	fmt.Println("Performed", n, "limit-25 frequency sorted searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words[:2048] {
		SearchEngine.ErrorCorrectingQuery(string(Query)+"0", 5, Correction)
		n++
	}
	fmt.Println("Performed", n, "limit-5 error correcting searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words[:2048] {
		SearchEngine.ErrorCorrectingQuery(string(Query)+"0", 25, Correction)
		n++
	}
	fmt.Println("Performed", n, "limit-25 error correcting searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words[:2048] {
		SearchEngine.SortedErrorCorrectingQuery(string(Query)+"0", 5, Correction, LengthSorter)
		n++
	}
	fmt.Println("Performed", n, "limit-5 length sorted error correcting searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words[:2048] {
		SearchEngine.SortedErrorCorrectingQuery(string(Query)+"0", 25, Correction, LengthSorter)
		n++
	}
	fmt.Println("Performed", n, "limit-25 length sorted error correcting searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words[:2048] {
		SearchEngine.SortedErrorCorrectingQuery(string(Query)+"0", 5, Correction, FreqSorter)
		n++
	}
	fmt.Println("Performed", n, "limit-5 frequency sorted error correcting searches in:", time.Now().Sub(t))
	t = time.Now()
	n = 0
	for _, Query := range SearchEngine.Words[:2048] {
		SearchEngine.SortedErrorCorrectingQuery(string(Query)+"0", 25, Correction, FreqSorter)
		n++
	}
	fmt.Println("Performed", n, "limit-25 frequency sorted error correcting searches in:", time.Now().Sub(t))
}
<|endoftext|>


<commit_before>package main

import (
	"strconv"

	"github.com/shirou/gopsutil/cpu"
)

// `cpuinfo` represent the CPU informations
type cpuinfo struct {
	count     string // number of CPUs
	vendorID  string // vendor name ex. AuthenticAMD, GenuineIntel
	modelName string // CPU model name
	cpuMhz    string //
}

// Get informations about the cpu by using `gopesutil` packages
func getCPUinfo() cpuinfo {
	info, err := cpu.Info() // cpu.Info() return a slice of InfoStat structs
	if err != nil {
		panic(err) //TODO do not panic but manage the error
	}

	result := cpuinfo{
		count:     strconv.Itoa(len(info)),
		vendorID:  info[0].VendorID, //BUG in `gopsutil`
		modelName: info[0].ModelName,
		cpuMhz:    strconv.FormatFloat(info[0].Mhz, 'f', 2, 64),
	}
	return result
}

//TODO count cores ?
//TODO count the physicals id = multiples sockets

//TODO We need to improve this. For now it take vendorID, modelName, etc from
//the first CPU assuming than all CPUs are the same (probably OK)and than there
//is only one socket (not true on servers)
//
// http://superuser.com/questions/388115/interpreting-output-of-cat-proc-cpuinfo
// http://unix.stackexchange.com/questions/146051/number-of-processors-in-proc-cpuinfo
//
<commit_msg>Improve display<commit_after>package main

import (
	"strconv"

	"github.com/shirou/gopsutil/cpu"
)

// `cpuinfo` represent the CPU informations
type cpuinfo struct {
	count     string // number of CPUs
	vendorID  string // vendor name ex. AuthenticAMD, GenuineIntel
	modelName string // CPU model name
	cpuMhz    string //
}

// Get informations about the cpu by using `gopesutil` packages
func getCPUinfo() cpuinfo {
	info, err := cpu.Info() // cpu.Info() return a slice of InfoStat structs
	if err != nil {
		panic(err) //TODO do not panic but manage the error
	}

	result := cpuinfo{
		count:     strconv.Itoa(len(info)),
		vendorID:  info[0].VendorID, //BUG in `gopsutil`
		modelName: info[0].ModelName,
		cpuMhz:    strconv.FormatFloat(info[0].Mhz, 'f', 0, 64),
	}
	return result
}

//TODO count cores ?
//TODO count the physicals id = multiples sockets

//TODO We need to improve this. For now it take vendorID, modelName, etc from
//the first CPU assuming than all CPUs are the same (probably OK)and than there
//is only one socket (not true on servers)
//
// http://superuser.com/questions/388115/interpreting-output-of-cat-proc-cpuinfo
// http://unix.stackexchange.com/questions/146051/number-of-processors-in-proc-cpuinfo
//
// TODO add temperature
<|endoftext|>


<commit_before>package nad

import (
	"bufio"
	"fmt"
	"io"
	"sync"

	"github.com/pkg/term"
)

// Client reprensents a client to the amplifier.
type Client struct {
	port         io.ReadWriteCloser
	mu           sync.Mutex
	EnableVolume bool
}

// New creates a new client to the amplifier, using device for communication.
func New(device string) (Client, error) {
	// From RS-232 Protocol for NAD Products v2.02:
	//
	// All communication should be done at a rate of 115200 bps with 8 data
	// bits, 1 stop bit and no parity bits. No flow control should be
	// performed.
	port, err := term.Open(device, term.Speed(115200), term.RawMode)
	if err != nil {
		return Client{}, err
	}
	return Client{port: port}, nil
}

// Close closes the underlying device
func (n *Client) Close() error {
	return n.port.Close()
}

// SendCmd validates and sends the command cmd to the amplifier.
func (n *Client) SendCmd(cmd Cmd) (Cmd, error) {
	// Check if volume adjustment is explicitly enabled. This check is done
	// because incorrect volume adjust might damage your amp, speakers
	// and/or cat.
	if cmd.Variable == "Volume" && !n.EnableVolume {
		return Cmd{}, fmt.Errorf("volume adjustment is not enabled")
	}
	if !cmd.Valid() {
		return Cmd{}, fmt.Errorf("invalid command: %s", cmd.String())
	}
	b, err := n.Send([]byte(cmd.Delimited()))
	if err != nil {
		return Cmd{}, err
	}
	return ParseCmd(string(b))
}

// SendString parses, validates and sends the command s.
func (n *Client) SendString(s string) (string, error) {
	cmd, err := ParseCmd(s)
	if err != nil {
		return "", err
	}
	reply, err := n.SendCmd(cmd)
	if err != nil {
		return "", err
	}
	return reply.String(), nil
}

// Send sends cmd to the amplifier without any preprocessing or validation.
func (n *Client) Send(cmd []byte) ([]byte, error) {
	n.mu.Lock()
	defer n.mu.Unlock()
	reader := bufio.NewReader(n.port)
	if _, err := n.port.Write(cmd); err != nil {
		return nil, err
	}
	// Discard newlines
	for {
		b, err := reader.ReadByte()
		if err != nil {
			return nil, err
		}
		// Rewind when we hit non-newline
		if b != '\n' {
			if err := reader.UnreadByte(); err != nil {
				return nil, err
			}
			break
		}
	}
	b, err := reader.ReadBytes('\n')
	if err != nil {
		return nil, err
	}
	return b, nil
}

// Model retrieves the amplifier model.
func (n *Client) Model() (Cmd, error) {
	cmd := Cmd{Variable: "Model", Operator: "?"}
	return n.SendCmd(cmd)
}

func (n *Client) enable(variable string, enable bool) (Cmd, error) {
	cmd := Cmd{Variable: variable, Operator: "="}
	if enable {
		cmd.Value = "On"
	} else {
		cmd.Value = "Off"
	}
	return n.SendCmd(cmd)
}

// Mute mutes the amplifier.
func (n *Client) Mute(enable bool) (Cmd, error) {
	return n.enable("Mute", enable)
}

// Power turns the amplifier on/off.
func (n *Client) Power(enable bool) (Cmd, error) {
	return n.enable("Power", enable)
}

// SpeakerA enables/disables output to speaker A.
func (n *Client) SpeakerA(enable bool) (Cmd, error) {
	return n.enable("SpeakerA", enable)
}

// SpeakerB enables/disables output to speaker B.
func (n *Client) SpeakerB(enable bool) (Cmd, error) {
	return n.enable("SpeakerB", enable)
}

// Tape1 enables/disables output to tape 1.
func (n *Client) Tape1(enable bool) (Cmd, error) {
	return n.enable("Tape1", enable)
}

// Source sets the current audio source, specified by src
func (n *Client) Source(src string) (Cmd, error) {
	cmd := Cmd{Variable: "Source", Operator: "=", Value: string(src)}
	return n.SendCmd(cmd)
}

// VolumeUp increases volume.
func (n *Client) VolumeUp() (Cmd, error) {
	cmd := Cmd{Variable: "Volume", Operator: "+"}
	return n.SendCmd(cmd)
}

// VolumeDown decreases volume.
func (n *Client) VolumeDown() (Cmd, error) {
	cmd := Cmd{Variable: "Volume", Operator: "-"}
	return n.SendCmd(cmd)
}
<commit_msg>Flush after reply has been read<commit_after>package nad

import (
	"bufio"
	"fmt"
	"io"
	"sync"

	"github.com/pkg/term"
)

// Client reprensents a client to the amplifier.
type Client struct {
	port         io.ReadWriteCloser
	mu           sync.Mutex
	EnableVolume bool
}

// New creates a new client to the amplifier, using device for communication.
func New(device string) (Client, error) {
	// From RS-232 Protocol for NAD Products v2.02:
	//
	// All communication should be done at a rate of 115200 bps with 8 data
	// bits, 1 stop bit and no parity bits. No flow control should be
	// performed.
	port, err := term.Open(device, term.Speed(115200), term.RawMode)
	if err != nil {
		return Client{}, err
	}
	return Client{port: port}, nil
}

// Close closes the underlying device
func (n *Client) Close() error {
	return n.port.Close()
}

// SendCmd validates and sends the command cmd to the amplifier.
func (n *Client) SendCmd(cmd Cmd) (Cmd, error) {
	// Check if volume adjustment is explicitly enabled. This check is done
	// because incorrect volume adjust might damage your amp, speakers
	// and/or cat.
	if cmd.Variable == "Volume" && !n.EnableVolume {
		return Cmd{}, fmt.Errorf("volume adjustment is not enabled")
	}
	if !cmd.Valid() {
		return Cmd{}, fmt.Errorf("invalid command: %s", cmd.String())
	}
	b, err := n.Send([]byte(cmd.Delimited()))
	if err != nil {
		return Cmd{}, err
	}
	return ParseCmd(string(b))
}

// SendString parses, validates and sends the command s.
func (n *Client) SendString(s string) (string, error) {
	cmd, err := ParseCmd(s)
	if err != nil {
		return "", err
	}
	reply, err := n.SendCmd(cmd)
	if err != nil {
		return "", err
	}
	return reply.String(), nil
}

// Send sends cmd to the amplifier without any preprocessing or validation.
func (n *Client) Send(cmd []byte) ([]byte, error) {
	n.mu.Lock()
	defer n.mu.Unlock()
	reader := bufio.NewReader(n.port)
	if _, err := n.port.Write(cmd); err != nil {
		return nil, err
	}
	// Discard newlines
	for {
		b, err := reader.ReadByte()
		if err != nil {
			return nil, err
		}
		// Rewind when we hit non-newline
		if b != '\n' {
			if err := reader.UnreadByte(); err != nil {
				return nil, err
			}
			break
		}
	}
	b, err := reader.ReadBytes('\n')
	if err != nil {
		return nil, err
	}
	// Discard data written but not transmitted, and data received but not read
	if t, ok := n.port.(*term.Term); ok {
		if err := t.Flush(); err != nil {
			return nil, err
		}
	}
	return b, nil
}

// Model retrieves the amplifier model.
func (n *Client) Model() (Cmd, error) {
	cmd := Cmd{Variable: "Model", Operator: "?"}
	return n.SendCmd(cmd)
}

func (n *Client) enable(variable string, enable bool) (Cmd, error) {
	cmd := Cmd{Variable: variable, Operator: "="}
	if enable {
		cmd.Value = "On"
	} else {
		cmd.Value = "Off"
	}
	return n.SendCmd(cmd)
}

// Mute mutes the amplifier.
func (n *Client) Mute(enable bool) (Cmd, error) {
	return n.enable("Mute", enable)
}

// Power turns the amplifier on/off.
func (n *Client) Power(enable bool) (Cmd, error) {
	return n.enable("Power", enable)
}

// SpeakerA enables/disables output to speaker A.
func (n *Client) SpeakerA(enable bool) (Cmd, error) {
	return n.enable("SpeakerA", enable)
}

// SpeakerB enables/disables output to speaker B.
func (n *Client) SpeakerB(enable bool) (Cmd, error) {
	return n.enable("SpeakerB", enable)
}

// Tape1 enables/disables output to tape 1.
func (n *Client) Tape1(enable bool) (Cmd, error) {
	return n.enable("Tape1", enable)
}

// Source sets the current audio source, specified by src
func (n *Client) Source(src string) (Cmd, error) {
	cmd := Cmd{Variable: "Source", Operator: "=", Value: string(src)}
	return n.SendCmd(cmd)
}

// VolumeUp increases volume.
func (n *Client) VolumeUp() (Cmd, error) {
	cmd := Cmd{Variable: "Volume", Operator: "+"}
	return n.SendCmd(cmd)
}

// VolumeDown decreases volume.
func (n *Client) VolumeDown() (Cmd, error) {
	cmd := Cmd{Variable: "Volume", Operator: "-"}
	return n.SendCmd(cmd)
}
<|endoftext|>


<commit_before>//
// Variable frequency CPU usage sampling on Linux via /proc
// Maybe this will turn into something like prstat on Solaris
//

// TOOD - check for rollover
// TODO - pull in /proc/schedstat
// TODO - check max field length for assumed present fields

package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"runtime/pprof"
	"sort"
	"time"
)

const histMin = 0
const histMax = 100000000
const histSigFigs = 2

func main() {
	var interval = flag.Int("i", 1000, "interval (ms) between measurements")
	var samples = flag.Int("s", 60, "sample counts to aggregate for output")
	var topN = flag.Int("n", 10, "show top N processes")
	var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
	var jiffy = flag.Int("jiffy", 100, "length of a jiffy")

	flag.Parse()

	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		if err = pprof.StartCPUProfile(f); err != nil {
			log.Fatal(err)
		}
	}

	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, os.Interrupt)

	go func() {
		_ = <-sigChan
		pprof.StopCPUProfile()
		fmt.Fprintln(os.Stderr, "SIGINT, probably")
		os.Exit(0)
	}()

	procCur := make(procStatsMap)
	procPrev := make(procStatsMap)
	procSum := make(procStatsMap)
	procHist := make(procStatsHistMap)

	schedCur := make(schedStatsMap)
	schedPrev := make(schedStatsMap)
	schedSum := make(schedStatsMap)

	var sysCur *systemStats
	var sysPrev *systemStats
	var sysSum *systemStats
	var sysHist *systemStatsHist

	var t1, t2 time.Time

	// run all scans one time to establish a baseline
	pids := getPidList()

	schedPrev = schedReaderPids(pids)
	t1 = time.Now()
	procPrev = statReader(pids)
	sysPrev = statReaderGlobal()
	sysSum = &systemStats{}
	sysHist = &systemStatsHist{}
	t2 = time.Now()

	targetSleep := time.Duration(*interval) * time.Millisecond
	adjustedSleep := targetSleep - t2.Sub(t1)

	for {
		for count := 0; count < *samples; count++ {
			time.Sleep(adjustedSleep)

			t1 = time.Now()
			pids = getPidList()

			procCur = statReader(pids)
			statRecord(procCur, procPrev, procSum, procHist)
			procPrev = procCur

			sysCur = statReaderGlobal()
			statsRecordGlobal(sysCur, sysPrev, sysSum, sysHist)
			sysPrev = sysCur

			t2 = time.Now()
			adjustedSleep = targetSleep - t2.Sub(t1)
		}

		topHist := sortList(procHist, *topN)
		topPids := make(pidlist, *topN)
		for i := 0; i < *topN; i++ {
			topPids[i] = topHist[i].pid
		}

		schedCur = schedReaderPids(topPids)
		schedRecord(schedCur, schedPrev, schedSum)
		schedPrev = schedCur

		dumpStats(procSum, procHist, sysSum, sysHist, schedSum, topN, jiffy, interval, samples)
		procHist = make(procStatsHistMap)
		procSum = make(procStatsMap)
		sysHist = &systemStatsHist{}
		sysSum = &systemStats{}
		t2 = time.Now()
		adjustedSleep = targetSleep - t2.Sub(t1)
	}
}

type bar struct {
	baz int
}

// Wrapper to sort histograms by max but remember which pid they are
type sortHist struct {
	pid  int
	hist *procStatsHist
}

// ByMax sorts stats by max usage
type ByMax []*sortHist

func (m ByMax) Len() int {
	return len(m)
}
func (m ByMax) Swap(i, j int) {
	m[i], m[j] = m[j], m[i]
}
func (m ByMax) Less(i, j int) bool {
	maxI := maxList([]float64{
		m[i].hist.ustime.Mean(),
		m[i].hist.custime.Mean(),
		m[i].hist.delayacctBlkioTicks.Mean(),
	})
	maxJ := maxList([]float64{
		m[j].hist.ustime.Mean(),
		m[j].hist.custime.Mean(),
		m[j].hist.delayacctBlkioTicks.Mean(),
	})
	return maxI > maxJ
}
func maxList(list []float64) float64 {
	ret := list[0]
	for i := 1; i < len(list); i++ {
		if list[i] > ret {
			ret = list[i]
		}
	}
	return ret
}

func sortList(histStats procStatsHistMap, limit int) []*sortHist {
	var list []*sortHist

	for pid, hist := range histStats {
		list = append(list, &sortHist{pid, hist})
	}
	sort.Sort(ByMax(list))
	if len(list) > limit {
		list = list[:limit]
	}

	return list
}

func formatMem(num uint64) string {
	letter := string("K")

	num = num * 4
	if num >= 10000 {
		num = (num + 512) / 1024
		letter = "M"
		if num >= 10000 {
			num = (num + 512) / 1024
			letter = "G"
		}
	}
	return fmt.Sprintf("%d%s", num, letter)
}

func dumpStats(sumStats procStatsMap, histStats procStatsHistMap, sysSum *systemStats, sysHist *systemStatsHist,
	sumSched schedStatsMap, topN, jiffy, interval, samples *int) {

	scale := func(val float64) float64 {
		return val / float64(*jiffy) / float64(*interval) * 1000 * 100
	}
	scaleSum := func(val float64, count int64) float64 {
		valSec := val / float64(*jiffy)
		sampleSec := float64(*interval) * float64(count) / 1000.0
		ret := (valSec / sampleSec) * 100
		return ret
	}
	scaleSched := func(val float64) float64 {
		return val / float64(*jiffy) / float64((*interval)*(*samples)) * 100
	}

	fmt.Printf("usr:    %4s/%4s/%4s   sys:%4s/%4s/%4s  nice:%4s/%4s/%4s    idle:%4s/%4s/%4s\n",
		trim(scale(float64(sysHist.usr.Min())), 4),
		trim(scale(float64(sysHist.usr.Max())), 4),
		trim(scale(sysHist.usr.Mean()), 4),

		trim(scale(float64(sysHist.sys.Min())), 4),
		trim(scale(float64(sysHist.sys.Max())), 4),
		trim(scale(sysHist.sys.Mean()), 4),

		trim(scale(float64(sysHist.nice.Min())), 4),
		trim(scale(float64(sysHist.nice.Max())), 4),
		trim(scale(sysHist.nice.Mean()), 4),

		trim(scale(float64(sysHist.idle.Min())), 4),
		trim(scale(float64(sysHist.idle.Max())), 4),
		trim(scale(sysHist.idle.Mean()), 4),
	)
	fmt.Printf("iowait: %4s/%4s/%4s  ctxt:%4s/%4s/%4s  prun:%4s/%4s/%4s  pblock:%4s/%4s/%4s  pstart: %4d\n",
		trim(scale(float64(sysHist.iowait.Min())), 4),
		trim(scale(float64(sysHist.iowait.Max())), 4),
		trim(scale(sysHist.iowait.Mean()), 4),

		trim(scale(float64(sysHist.ctxt.Min())), 4),
		trim(scale(float64(sysHist.ctxt.Max())), 4),
		trim(scale(sysHist.ctxt.Mean()), 4),

		trim(float64(sysHist.procsRunning.Min()), 4),
		trim(float64(sysHist.procsRunning.Max()), 4),
		trim(sysHist.procsRunning.Mean(), 4),

		trim(float64(sysHist.procsBlocked.Min()), 4),
		trim(float64(sysHist.procsBlocked.Max()), 4),
		trim(sysHist.procsBlocked.Mean(), 4),

		sysSum.procsTotal,
	)

	list := sortList(histStats, *topN)

	fmt.Print("                comm     pid     min     max     usr     sys   ctime    slat     ctx     icx     rss  iowait thrd  sam\n")
	for _, thisStat := range list {
		hist := thisStat.hist
		pid := thisStat.pid
		var schedWait, nrSwitches, nrInvoluntarySwitches string
		sched, ok := sumSched[pid]
		if ok == true {
			schedWait = trim(scaleSched(sched.waitSum), 7)
			nrSwitches = fmt.Sprintf("%d", sched.nrSwitches)
			nrInvoluntarySwitches = fmt.Sprintf("%d", sched.nrInvoluntarySwitches)
		} else {
			schedWait = "-"
			nrSwitches = "-"
			nrInvoluntarySwitches = "-"
		}
		sampleCount := hist.utime.TotalCount()
		fmt.Printf("%20s %7d %7s %7s %7s %7s %7s %7s %7s %7s %7s %7s %4d %4d\n",
			sumStats[pid].comm,
			pid,
			trim(scale(float64(hist.ustime.Min())), 7),
			trim(scale(float64(hist.ustime.Max())), 7),
			trim(scaleSum(float64(sumStats[pid].utime), sampleCount), 7),
			trim(scaleSum(float64(sumStats[pid].stime), sampleCount), 7),
			trim(scaleSum(float64(sumStats[pid].cutime+sumStats[pid].cstime), sampleCount), 7),
			schedWait,
			nrSwitches,
			nrInvoluntarySwitches,
			formatMem(sumStats[pid].rss),
			trim(scaleSum(float64(sumStats[pid].delayacctBlkioTicks), sampleCount), 7),
			sumStats[pid].numThreads,
			sampleCount,
		)
	}
	fmt.Println()
}
<commit_msg>TODOs are TODONE<commit_after>//
// Variable frequency CPU usage sampling on Linux via /proc
// Maybe this will turn into something like prstat on Solaris
//

// TOOD - check for rollover
// TODO - check max field length for assumed present fields

package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"runtime/pprof"
	"sort"
	"time"
)

const histMin = 0
const histMax = 100000000
const histSigFigs = 2

func main() {
	var interval = flag.Int("i", 1000, "interval (ms) between measurements")
	var samples = flag.Int("s", 60, "sample counts to aggregate for output")
	var topN = flag.Int("n", 10, "show top N processes")
	var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
	var jiffy = flag.Int("jiffy", 100, "length of a jiffy")

	flag.Parse()

	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		if err = pprof.StartCPUProfile(f); err != nil {
			log.Fatal(err)
		}
	}

	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, os.Interrupt)

	go func() {
		_ = <-sigChan
		pprof.StopCPUProfile()
		fmt.Fprintln(os.Stderr, "SIGINT, probably")
		os.Exit(0)
	}()

	procCur := make(procStatsMap)
	procPrev := make(procStatsMap)
	procSum := make(procStatsMap)
	procHist := make(procStatsHistMap)

	schedCur := make(schedStatsMap)
	schedPrev := make(schedStatsMap)
	schedSum := make(schedStatsMap)

	var sysCur *systemStats
	var sysPrev *systemStats
	var sysSum *systemStats
	var sysHist *systemStatsHist

	var t1, t2 time.Time

	// run all scans one time to establish a baseline
	pids := getPidList()

	schedPrev = schedReaderPids(pids)
	t1 = time.Now()
	procPrev = statReader(pids)
	sysPrev = statReaderGlobal()
	sysSum = &systemStats{}
	sysHist = &systemStatsHist{}
	t2 = time.Now()

	targetSleep := time.Duration(*interval) * time.Millisecond
	adjustedSleep := targetSleep - t2.Sub(t1)

	for {
		for count := 0; count < *samples; count++ {
			time.Sleep(adjustedSleep)

			t1 = time.Now()
			pids = getPidList()

			procCur = statReader(pids)
			statRecord(procCur, procPrev, procSum, procHist)
			procPrev = procCur

			sysCur = statReaderGlobal()
			statsRecordGlobal(sysCur, sysPrev, sysSum, sysHist)
			sysPrev = sysCur

			t2 = time.Now()
			adjustedSleep = targetSleep - t2.Sub(t1)
		}

		topHist := sortList(procHist, *topN)
		topPids := make(pidlist, *topN)
		for i := 0; i < *topN; i++ {
			topPids[i] = topHist[i].pid
		}

		schedCur = schedReaderPids(topPids)
		schedRecord(schedCur, schedPrev, schedSum)
		schedPrev = schedCur

		dumpStats(procSum, procHist, sysSum, sysHist, schedSum, topN, jiffy, interval, samples)
		procHist = make(procStatsHistMap)
		procSum = make(procStatsMap)
		sysHist = &systemStatsHist{}
		sysSum = &systemStats{}
		t2 = time.Now()
		adjustedSleep = targetSleep - t2.Sub(t1)
	}
}

type bar struct {
	baz int
}

// Wrapper to sort histograms by max but remember which pid they are
type sortHist struct {
	pid  int
	hist *procStatsHist
}

// ByMax sorts stats by max usage
type ByMax []*sortHist

func (m ByMax) Len() int {
	return len(m)
}
func (m ByMax) Swap(i, j int) {
	m[i], m[j] = m[j], m[i]
}
func (m ByMax) Less(i, j int) bool {
	maxI := maxList([]float64{
		m[i].hist.ustime.Mean(),
		m[i].hist.custime.Mean(),
		m[i].hist.delayacctBlkioTicks.Mean(),
	})
	maxJ := maxList([]float64{
		m[j].hist.ustime.Mean(),
		m[j].hist.custime.Mean(),
		m[j].hist.delayacctBlkioTicks.Mean(),
	})
	return maxI > maxJ
}
func maxList(list []float64) float64 {
	ret := list[0]
	for i := 1; i < len(list); i++ {
		if list[i] > ret {
			ret = list[i]
		}
	}
	return ret
}

func sortList(histStats procStatsHistMap, limit int) []*sortHist {
	var list []*sortHist

	for pid, hist := range histStats {
		list = append(list, &sortHist{pid, hist})
	}
	sort.Sort(ByMax(list))
	if len(list) > limit {
		list = list[:limit]
	}

	return list
}

func formatMem(num uint64) string {
	letter := string("K")

	num = num * 4
	if num >= 10000 {
		num = (num + 512) / 1024
		letter = "M"
		if num >= 10000 {
			num = (num + 512) / 1024
			letter = "G"
		}
	}
	return fmt.Sprintf("%d%s", num, letter)
}

func dumpStats(sumStats procStatsMap, histStats procStatsHistMap, sysSum *systemStats, sysHist *systemStatsHist,
	sumSched schedStatsMap, topN, jiffy, interval, samples *int) {

	scale := func(val float64) float64 {
		return val / float64(*jiffy) / float64(*interval) * 1000 * 100
	}
	scaleSum := func(val float64, count int64) float64 {
		valSec := val / float64(*jiffy)
		sampleSec := float64(*interval) * float64(count) / 1000.0
		ret := (valSec / sampleSec) * 100
		return ret
	}
	scaleSched := func(val float64) float64 {
		return val / float64(*jiffy) / float64((*interval)*(*samples)) * 100
	}

	fmt.Printf("usr:    %4s/%4s/%4s   sys:%4s/%4s/%4s  nice:%4s/%4s/%4s    idle:%4s/%4s/%4s\n",
		trim(scale(float64(sysHist.usr.Min())), 4),
		trim(scale(float64(sysHist.usr.Max())), 4),
		trim(scale(sysHist.usr.Mean()), 4),

		trim(scale(float64(sysHist.sys.Min())), 4),
		trim(scale(float64(sysHist.sys.Max())), 4),
		trim(scale(sysHist.sys.Mean()), 4),

		trim(scale(float64(sysHist.nice.Min())), 4),
		trim(scale(float64(sysHist.nice.Max())), 4),
		trim(scale(sysHist.nice.Mean()), 4),

		trim(scale(float64(sysHist.idle.Min())), 4),
		trim(scale(float64(sysHist.idle.Max())), 4),
		trim(scale(sysHist.idle.Mean()), 4),
	)
	fmt.Printf("iowait: %4s/%4s/%4s  ctxt:%4s/%4s/%4s  prun:%4s/%4s/%4s  pblock:%4s/%4s/%4s  pstart: %4d\n",
		trim(scale(float64(sysHist.iowait.Min())), 4),
		trim(scale(float64(sysHist.iowait.Max())), 4),
		trim(scale(sysHist.iowait.Mean()), 4),

		trim(scale(float64(sysHist.ctxt.Min())), 4),
		trim(scale(float64(sysHist.ctxt.Max())), 4),
		trim(scale(sysHist.ctxt.Mean()), 4),

		trim(float64(sysHist.procsRunning.Min()), 4),
		trim(float64(sysHist.procsRunning.Max()), 4),
		trim(sysHist.procsRunning.Mean(), 4),

		trim(float64(sysHist.procsBlocked.Min()), 4),
		trim(float64(sysHist.procsBlocked.Max()), 4),
		trim(sysHist.procsBlocked.Mean(), 4),

		sysSum.procsTotal,
	)

	list := sortList(histStats, *topN)

	fmt.Print("                comm     pid     min     max     usr     sys   ctime    slat     ctx     icx     rss  iowait thrd  sam\n")
	for _, thisStat := range list {
		hist := thisStat.hist
		pid := thisStat.pid
		var schedWait, nrSwitches, nrInvoluntarySwitches string
		sched, ok := sumSched[pid]
		if ok == true {
			schedWait = trim(scaleSched(sched.waitSum), 7)
			nrSwitches = fmt.Sprintf("%d", sched.nrSwitches)
			nrInvoluntarySwitches = fmt.Sprintf("%d", sched.nrInvoluntarySwitches)
		} else {
			schedWait = "-"
			nrSwitches = "-"
			nrInvoluntarySwitches = "-"
		}
		sampleCount := hist.utime.TotalCount()
		fmt.Printf("%20s %7d %7s %7s %7s %7s %7s %7s %7s %7s %7s %7s %4d %4d\n",
			sumStats[pid].comm,
			pid,
			trim(scale(float64(hist.ustime.Min())), 7),
			trim(scale(float64(hist.ustime.Max())), 7),
			trim(scaleSum(float64(sumStats[pid].utime), sampleCount), 7),
			trim(scaleSum(float64(sumStats[pid].stime), sampleCount), 7),
			trim(scaleSum(float64(sumStats[pid].cutime+sumStats[pid].cstime), sampleCount), 7),
			schedWait,
			nrSwitches,
			nrInvoluntarySwitches,
			formatMem(sumStats[pid].rss),
			trim(scaleSum(float64(sumStats[pid].delayacctBlkioTicks), sampleCount), 7),
			sumStats[pid].numThreads,
			sampleCount,
		)
	}
	fmt.Println()
}
<|endoftext|>


<commit_before>package octorrent

import (
	"bufio"
	"bytes"
	"math"
	"reflect"
	"strconv"
	"testing"
)

func getDecoder(d []byte) decoder {
	buf := bytes.NewBuffer(d)

	return decoder{
		*bufio.NewReader(buf),
	}
}

func TestReadInt(t *testing.T) {
	i, o := "412e51", int64(412)
	dec := getDecoder([]byte(i))

	if num, err := dec.readInt(); err != nil {
		t.Errorf("readInt returned error: %v", err)
	} else if num != o {
		t.Errorf("readInt did return %i, but should return %i", num, o)
	}
}

func TestReadIntUntil(t *testing.T) {
	i, o := "142", int64(14)
	dec := getDecoder([]byte(i))

	if num, err := dec.readIntUntil('2'); err != nil {
		t.Errorf("readIntUntil returned error: %v", err)
	} else if num != o {
		t.Errorf("readIntUntil did return %i, but should return %i", num, o)
	}

	// Check broken reader
	dec = getDecoder([]byte(""))
	if _, err := dec.readIntUntil('t'); err == nil {
		t.Errorf("readIntUntil with empty reader returned no error, but should")
	}

	dec = getDecoder([]byte("test"))
	if _, err := dec.readIntUntil('e'); err == nil {
		t.Errorf("readIntUntil with no digits returned no error, but should")
	}

	// Check unsigned int
	var ui uint64
	ui = math.MaxInt64 + 1
	i = "i" + strconv.FormatUint(ui, 10) + "e"
	dec = getDecoder([]byte(i))
	if _, err := dec.readIntUntil('e'); err == nil {
		t.Errorf("readIntUntil with unsigned int returned no error, but should")
	}
}

func TestReadString(t *testing.T) {
	i, o := "4:testfoobar", "test"
	dec := getDecoder([]byte(i))
	if str, err := dec.readString(); err != nil {
		t.Errorf("readString returned error: %v", err)
	} else if str != o {
		t.Errorf("readString returned %s, but should return %s", str, o)
	}

	// Test broken reader
	dec = getDecoder([]byte(""))
	if _, err := dec.readString(); err == nil {
		t.Errorf("readSstring with empty buffer returned no error, but should")
	}

	// Test wrong format
	dec = getDecoder([]byte("4:foo"))
	if _, err := dec.readString(); err == nil {
		t.Errorf("readString with wrong formatted string returned no error, but should")
	}
}

func TestReadValue(t *testing.T) {
	dec := getDecoder([]byte(""))
	if _, err := dec.readValue(); err == nil {
		t.Errorf("readValue with empty buffer returned no error, but should")
	}

	dec = getDecoder([]byte("ifooe"))
	if _, err := dec.readValue(); err == nil {
		t.Errorf("readValue with wrongly formatted buffer returned no error, but should")
	}
}

func TestIsEnd(t *testing.T) {
	i, o := "4:test", false
	dec := getDecoder([]byte(i))
	if end, err := dec.isEnd(); err != nil {
		t.Errorf("isEnd returned error: %v", err)
	} else if end != o {
		t.Errorf("isEnd returned %v, but should return %v", end, o)
	}

	i, o = "e4:test", true
	dec = getDecoder([]byte(i))
	if end, err := dec.isEnd(); err != nil {
		t.Errorf("isEnd returned error: %v", err)
	} else if end != o {
		t.Errorf("isEnd returned %v, but should return %v", end, o)
	}

	dec = getDecoder([]byte(""))
	if _, err := dec.isEnd(); err == nil {
		t.Errorf("isEnd with empty buffer returned no error, but should")
	}
}

func TestReadList(t *testing.T) {
	i := "4:testi4ee"
	o := []interface{}{"test", int64(4)}
	dec := getDecoder([]byte(i))

	if list, err := dec.readList(); err != nil {
		t.Errorf("readList returned error: %v", err)
	} else if !reflect.DeepEqual(list, o) {
		t.Errorf("readList returned %v, but should return %v", list, o)
	}

	dec = getDecoder([]byte(""))
	if _, err := dec.readList(); err == nil {
		t.Errorf("readList with empty buffer returned no error, but should")
	}

	dec = getDecoder([]byte("4:test"))
	if _, err := dec.readList(); err == nil {
		t.Errorf("readList with no 'e'nd returned no error, but should")
	}

	dec = getDecoder([]byte("ie"))
	if _, err := dec.readList(); err == nil {
		t.Errorf("readList with no valid value returned no error, but should")
	}
}

func TestReadDictionary(t *testing.T) {
	i := "4:testi1337e3:foo3:bare"
	o := map[string]interface{}{
		"test": int64(1337),
		"foo":  "bar",
	}
	dec := getDecoder([]byte(i))

	if dict, err := dec.readDictionary(); err != nil {
		t.Errorf("readDictionary returned error: %v", err)
	} else if !reflect.DeepEqual(dict, o) {
		t.Errorf("readDictionary returned %v, but should %v", dict, o)
	}

	dec = getDecoder([]byte(""))
	if _, err := dec.readDictionary(); err == nil {
		t.Errorf("readDict with empty buffer returned no error, but should")
	}

	dec = getDecoder([]byte(":"))
	if _, err := dec.readDictionary(); err == nil {
		t.Errorf("readDict with invalid key returned no error, but should")
	}

	dec = getDecoder([]byte("3:fooe"))
	if _, err := dec.readDictionary(); err == nil {
		t.Errorf("readDict with no value returned no error, but should")
	}

	dec = getDecoder([]byte("3:foo"))
	if _, err := dec.readDictionary(); err == nil {
		t.Errorf("readDict with only one key and no value returned no error, but should")
	}

	dec = getDecoder([]byte("3:foo3:bar"))
	if _, err := dec.readDictionary(); err == nil {
		t.Errorf("readDict with no 'e'nd returned no error, but should")
	}
}

func TestDecode(t *testing.T) {
	const i = "d4:testli4ei3ee3:foo3:bare"
	o := map[string]interface{}{
		"test": []interface{}{
			int64(4),
			int64(3),
		},
		"foo": "bar",
	}
	buf := bytes.NewBufferString(i)

	if res, err := Decode(buf); err != nil {
		t.Errorf("Decode returned error: %v", err)
	} else if !reflect.DeepEqual(res, o) {
		t.Errorf("Decode returned %v, but should return %v", res, o)
	}

	buf = bytes.NewBufferString("")
	if _, err := Decode(buf); err == nil {
		t.Errorf("Decode with empty buffer returned no error, but should")
	}

	buf = bytes.NewBufferString("3:foo")
	if _, err := Decode(buf); err == nil {
		t.Errorf("Decode with other value than dictionary returned no error, but should")
	}
}
<commit_msg>Add test for biggest int possible<commit_after>package octorrent

import (
	"bufio"
	"bytes"
	"math"
	"reflect"
	"strconv"
	"testing"
)

func getDecoder(d []byte) decoder {
	buf := bytes.NewBuffer(d)

	return decoder{
		*bufio.NewReader(buf),
	}
}

func TestReadInt(t *testing.T) {
	i, o := "412e51", int64(412)
	dec := getDecoder([]byte(i))

	if num, err := dec.readInt(); err != nil {
		t.Errorf("readInt returned error: %v", err)
	} else if num != o {
		t.Errorf("readInt did return %i, but should return %i", num, o)
	}
}

func TestReadIntUntil(t *testing.T) {
	i, o := "142", int64(14)
	dec := getDecoder([]byte(i))

	if num, err := dec.readIntUntil('2'); err != nil {
		t.Errorf("readIntUntil returned error: %v", err)
	} else if num != o {
		t.Errorf("readIntUntil did return %i, but should return %i", num, o)
	}

	// Check unsigned int
	var max uint64
	max = math.MaxUint64
	i = strconv.FormatUint(math.MaxUint64, 10) + "e"
	dec = getDecoder([]byte(i))
	if num, err := dec.readIntUntil('e'); err != nil {
		t.Errorf("readIntUntil with unsigned int returned error: %v", err)
	} else if num.(uint64) != math.MaxUint64 {
		t.Errorf("readIntUntil with unsigned int did return %i, but should return %i", num, max)
	}

	// Check broken reader
	dec = getDecoder([]byte(""))
	if _, err := dec.readIntUntil('t'); err == nil {
		t.Errorf("readIntUntil with empty reader returned no error, but should")
	}

	dec = getDecoder([]byte("test"))
	if _, err := dec.readIntUntil('e'); err == nil {
		t.Errorf("readIntUntil with no digits returned no error, but should")
	}
}

func TestReadString(t *testing.T) {
	i, o := "4:testfoobar", "test"
	dec := getDecoder([]byte(i))
	if str, err := dec.readString(); err != nil {
		t.Errorf("readString returned error: %v", err)
	} else if str != o {
		t.Errorf("readString returned %s, but should return %s", str, o)
	}

	// Test broken reader
	dec = getDecoder([]byte(""))
	if _, err := dec.readString(); err == nil {
		t.Errorf("readSstring with empty buffer returned no error, but should")
	}

	// Test wrong format
	dec = getDecoder([]byte("4:foo"))
	if _, err := dec.readString(); err == nil {
		t.Errorf("readString with wrong formatted string returned no error, but should")
	}
}

func TestReadValue(t *testing.T) {
	dec := getDecoder([]byte(""))
	if _, err := dec.readValue(); err == nil {
		t.Errorf("readValue with empty buffer returned no error, but should")
	}

	dec = getDecoder([]byte("ifooe"))
	if _, err := dec.readValue(); err == nil {
		t.Errorf("readValue with wrongly formatted buffer returned no error, but should")
	}
}

func TestIsEnd(t *testing.T) {
	i, o := "4:test", false
	dec := getDecoder([]byte(i))
	if end, err := dec.isEnd(); err != nil {
		t.Errorf("isEnd returned error: %v", err)
	} else if end != o {
		t.Errorf("isEnd returned %v, but should return %v", end, o)
	}

	i, o = "e4:test", true
	dec = getDecoder([]byte(i))
	if end, err := dec.isEnd(); err != nil {
		t.Errorf("isEnd returned error: %v", err)
	} else if end != o {
		t.Errorf("isEnd returned %v, but should return %v", end, o)
	}

	dec = getDecoder([]byte(""))
	if _, err := dec.isEnd(); err == nil {
		t.Errorf("isEnd with empty buffer returned no error, but should")
	}
}

func TestReadList(t *testing.T) {
	i := "4:testi4ee"
	o := []interface{}{"test", int64(4)}
	dec := getDecoder([]byte(i))

	if list, err := dec.readList(); err != nil {
		t.Errorf("readList returned error: %v", err)
	} else if !reflect.DeepEqual(list, o) {
		t.Errorf("readList returned %v, but should return %v", list, o)
	}

	dec = getDecoder([]byte(""))
	if _, err := dec.readList(); err == nil {
		t.Errorf("readList with empty buffer returned no error, but should")
	}

	dec = getDecoder([]byte("4:test"))
	if _, err := dec.readList(); err == nil {
		t.Errorf("readList with no 'e'nd returned no error, but should")
	}

	dec = getDecoder([]byte("ie"))
	if _, err := dec.readList(); err == nil {
		t.Errorf("readList with no valid value returned no error, but should")
	}
}

func TestReadDictionary(t *testing.T) {
	i := "4:testi1337e3:foo3:bare"
	o := map[string]interface{}{
		"test": int64(1337),
		"foo":  "bar",
	}
	dec := getDecoder([]byte(i))

	if dict, err := dec.readDictionary(); err != nil {
		t.Errorf("readDictionary returned error: %v", err)
	} else if !reflect.DeepEqual(dict, o) {
		t.Errorf("readDictionary returned %v, but should %v", dict, o)
	}

	dec = getDecoder([]byte(""))
	if _, err := dec.readDictionary(); err == nil {
		t.Errorf("readDict with empty buffer returned no error, but should")
	}

	dec = getDecoder([]byte(":"))
	if _, err := dec.readDictionary(); err == nil {
		t.Errorf("readDict with invalid key returned no error, but should")
	}

	dec = getDecoder([]byte("3:fooe"))
	if _, err := dec.readDictionary(); err == nil {
		t.Errorf("readDict with no value returned no error, but should")
	}

	dec = getDecoder([]byte("3:foo"))
	if _, err := dec.readDictionary(); err == nil {
		t.Errorf("readDict with only one key and no value returned no error, but should")
	}

	dec = getDecoder([]byte("3:foo3:bar"))
	if _, err := dec.readDictionary(); err == nil {
		t.Errorf("readDict with no 'e'nd returned no error, but should")
	}
}

func TestDecode(t *testing.T) {
	const i = "d4:testli4ei3ee3:foo3:bare"
	o := map[string]interface{}{
		"test": []interface{}{
			int64(4),
			int64(3),
		},
		"foo": "bar",
	}
	buf := bytes.NewBufferString(i)

	if res, err := Decode(buf); err != nil {
		t.Errorf("Decode returned error: %v", err)
	} else if !reflect.DeepEqual(res, o) {
		t.Errorf("Decode returned %v, but should return %v", res, o)
	}

	buf = bytes.NewBufferString("")
	if _, err := Decode(buf); err == nil {
		t.Errorf("Decode with empty buffer returned no error, but should")
	}

	buf = bytes.NewBufferString("3:foo")
	if _, err := Decode(buf); err == nil {
		t.Errorf("Decode with other value than dictionary returned no error, but should")
	}
}
<|endoftext|>