<commit_before>package ecqltest

import (
	"github.com/betable/mock"
	"github.com/maraino/ecql"
)

// Batch is a mock implementation of the Batch interface
type Batch struct {
	mock.Mock
}

// Add is mocks a call to this method.
func (m *Batch) Add(s ...ecql.Statement) ecql.Batch {
	ret := m.Called(s)
	ret0, _ := ret.Get(0).(ecql.Batch)
	return ret0
}

// Apply is mocks a call to this method.
func (m *Batch) Apply() error {
	ret := m.Called()
	ret0, _ := ret.Get(0).(error)
	return ret0
}

// ApplyCAS is mocks a call to this method.
func (m *Batch) ApplyCAS() (bool, error) {
	ret := m.Called()
	ret0, _ := ret.Get(0).(bool)
	ret1, _ := ret.Get(1).(error)
	return ret0, ret1
}
<commit_msg>Use proper go-mock package.<commit_after>package ecqltest

import (
	"github.com/maraino/ecql"
	"github.com/maraino/go-mock"
)

// Batch is a mock implementation of the Batch interface
type Batch struct {
	mock.Mock
}

// Add is mocks a call to this method.
func (m *Batch) Add(s ...ecql.Statement) ecql.Batch {
	ret := m.Called(s)
	ret0, _ := ret.Get(0).(ecql.Batch)
	return ret0
}

// Apply is mocks a call to this method.
func (m *Batch) Apply() error {
	ret := m.Called()
	ret0, _ := ret.Get(0).(error)
	return ret0
}

// ApplyCAS is mocks a call to this method.
func (m *Batch) ApplyCAS() (bool, error) {
	ret := m.Called()
	ret0, _ := ret.Get(0).(bool)
	ret1, _ := ret.Get(1).(error)
	return ret0, ret1
}
<|endoftext|>


<commit_before>package plugins

import (
    "github.com/bwmarrin/discordgo"
    "github.com/sn0w/Karen/cache"
    "github.com/sn0w/Karen/helpers"
    "github.com/sn0w/Karen/metrics"
    "strings"
)

// Plugin interface to enforce a basic structure
type Plugin interface {
    // List of commands and aliases
    Commands() []string

    // Plugin constructor
    Init(session *discordgo.Session)

    // Action to execute on message receive
    Action(
    command string,
    content string,
    msg *discordgo.Message,
    session *discordgo.Session,
    )
}

type TriggerPlugin interface {
    Init(session *discordgo.Session)
    Action(msg *discordgo.Message, session *discordgo.Session)
}

// PluginList is the list of active plugins
var PluginList = []Plugin{
    Avatar{},
    About{},
    Stats{},
    Ping{},
    Invite{},
    Giphy{},
    Google{},
    RandomCat{},
    Stone{},
    Roll{},
    Reminders{},
    &Music{},
    UrbanDict{},
    Weather{},
    Minecraft{},
    XKCD{},
}

// TriggerPluginList is the list of plugins that activate on normal chat
var TriggerPluginList = []TriggerPlugin{}

// CallBotPlugin iterates through the list of registered
// plugins and tries to guess which one is the intended call
// Fist match wins.
//
// command - The command that triggered this execution
// content - The content without command
// msg     - The message object
// session - The discord session
func CallBotPlugin(command string, content string, msg *discordgo.Message) {
    // Iterate over all plugins
    for _, plug := range PluginList {
        // Iterate over all commands of the current plugin
        for _, cmd := range plug.Commands() {
            if command == cmd {
                go safePluginCall(command, strings.TrimSpace(content), msg, plug)
                break
            }
        }
    }
}

// CallTriggerPlugins iterates through all trigger plugins
// and calls *all* of them (async).
//
// msg     - The message that triggered the execution
// session - The discord session
func CallTriggerPlugins(msg *discordgo.Message) {
    // Iterate over all plugins
    for _, plug := range TriggerPluginList {
        go func(plugin TriggerPlugin) {
            defer helpers.RecoverDiscord(msg)
            plugin.Action(msg, cache.GetSession())
        }(plug)
    }
}

// Wrapper that catches any panics from plugins
// Arguments: Same as CallBotPlugin().
func safePluginCall(command string, content string, msg *discordgo.Message, plug Plugin) {
    defer helpers.RecoverDiscord(msg)
    metrics.CommandsExecuted.Add(1)
    plug.Action(command, content, msg, cache.GetSession())
}
<commit_msg>Reorder plugins<commit_after>package plugins

import (
    "github.com/bwmarrin/discordgo"
    "github.com/sn0w/Karen/cache"
    "github.com/sn0w/Karen/helpers"
    "github.com/sn0w/Karen/metrics"
    "strings"
)

// Plugin interface to enforce a basic structure
type Plugin interface {
    // List of commands and aliases
    Commands() []string

    // Plugin constructor
    Init(session *discordgo.Session)

    // Action to execute on message receive
    Action(
    command string,
    content string,
    msg *discordgo.Message,
    session *discordgo.Session,
    )
}

type TriggerPlugin interface {
    Init(session *discordgo.Session)
    Action(msg *discordgo.Message, session *discordgo.Session)
}

// PluginList is the list of active plugins
var PluginList = []Plugin{
    About{},
    Avatar{},
    Giphy{},
    Google{},
    Invite{},
    Lenny{},
    Minecraft{},
    &Music{},
    Ping{},
    RandomCat{},
    Reminders{},
    Roll{},
    Shrug{},
    Stats{},
    Stone{},
    Support{},
    UrbanDict{},
    Weather{},
    XKCD{},
}

// TriggerPluginList is the list of plugins that activate on normal chat
var TriggerPluginList = []TriggerPlugin{}

// CallBotPlugin iterates through the list of registered
// plugins and tries to guess which one is the intended call
// Fist match wins.
//
// command - The command that triggered this execution
// content - The content without command
// msg     - The message object
// session - The discord session
func CallBotPlugin(command string, content string, msg *discordgo.Message) {
    // Iterate over all plugins
    for _, plug := range PluginList {
        // Iterate over all commands of the current plugin
        for _, cmd := range plug.Commands() {
            if command == cmd {
                go safePluginCall(command, strings.TrimSpace(content), msg, plug)
                break
            }
        }
    }
}

// CallTriggerPlugins iterates through all trigger plugins
// and calls *all* of them (async).
//
// msg     - The message that triggered the execution
// session - The discord session
func CallTriggerPlugins(msg *discordgo.Message) {
    // Iterate over all plugins
    for _, plug := range TriggerPluginList {
        go func(plugin TriggerPlugin) {
            defer helpers.RecoverDiscord(msg)
            plugin.Action(msg, cache.GetSession())
        }(plug)
    }
}

// Wrapper that catches any panics from plugins
// Arguments: Same as CallBotPlugin().
func safePluginCall(command string, content string, msg *discordgo.Message, plug Plugin) {
    defer helpers.RecoverDiscord(msg)
    metrics.CommandsExecuted.Add(1)
    plug.Action(command, content, msg, cache.GetSession())
}
<|endoftext|>


<commit_before>package plugins

import (
	"bytes"
	"fmt"
	"text/template"

	"github.com/osteele/gojekyll/utils"
	"github.com/osteele/liquid"
	"github.com/osteele/liquid/render"
	"github.com/tdewolff/minify"
	"github.com/tdewolff/minify/html"
)

type jekyllSEOTagPlugin struct {
	plugin
	site Site
	tpl  *liquid.Template
}

func init() {
	register("jekyll-seo-tag", &jekyllSEOTagPlugin{})
}

func (p *jekyllSEOTagPlugin) Initialize(s Site) error {
	p.site = s
	return nil
}

func (p *jekyllSEOTagPlugin) ConfigureTemplateEngine(e *liquid.Engine) error {
	e.RegisterTag("seo", p.seoTag)
	tpl, err := e.ParseTemplate([]byte(seoTagTemplateSource))
	if err != nil {
		panic(err)
	}
	p.tpl = tpl
	return nil
}

func (p *jekyllSEOTagPlugin) seoTag(ctx render.Context) (string, error) {
	buf := new(bytes.Buffer)
	e := seoTagTemplate.Execute(buf, seoTag{p.tpl, ctx})
	return buf.String(), e
}

type seoTag struct {
	tpl *liquid.Template
	ctx render.Context
}

var seoSiteFields = []string{"url", "twitter", "facebook", "logo", "social", "google_site_verification", "lang"}
var seoPageOrSiteFields = []string{"author", "description", "image", "author", "lang"}

func (p seoTag) TagBody() (string, error) {
	var (
		ctx          = p.ctx
		site         = liquid.FromDrop(ctx.Get("site")).(map[string]interface{})
		page         = liquid.FromDrop(ctx.Get("page")).(map[string]interface{})
		pageTitle    = page["title"]
		siteTitle    = site["title"]
		canonicalURL = fmt.Sprintf("%s%s", site["url"], page["url"])
	)
	if siteTitle == nil {
		siteTitle = site["name"]
	}
	seoTag := map[string]interface{}{
		"title?": true,
		"title":  siteTitle,
		// the following are not doc'ed, but evident from inspection:
		// FIXME canonical w|w/out site.url and site.prefix
		"canonical_url": canonicalURL,
		"page_lang":     "en_US",
		"page_title":    pageTitle,
		"site_title":    siteTitle,
	}
	copyFields(seoTag, site, append(seoSiteFields, seoPageOrSiteFields...))
	copyFields(seoTag, page, seoPageOrSiteFields)
	// seoTag["description"] = page["excerpt"] FIXME appears to behave something like following, but excerpt should not be processed
	if pageTitle != nil && siteTitle != nil && pageTitle != siteTitle {
		seoTag["title"] = fmt.Sprintf("%s | %s", pageTitle, siteTitle)
	}
	if author, ok := seoTag["author"].(string); ok {
		if data, _ := utils.FollowDots(site, []string{"data", "authors", author}); data != nil {
			seoTag["author"] = data
		}
	}
	seoTag["json_ld"] = makeJSONLD(seoTag)
	bindings := map[string]interface{}{
		"page":    page,
		"site":    site,
		"seo_tag": seoTag,
	}
	b, err := p.tpl.Render(bindings)
	if err != nil {
		return "", err
	}
	m := minify.New()
	m.AddFunc("text/html", html.Minify)
	min := bytes.NewBuffer(make([]byte, 0, len(b)))
	if err := m.Minify("text/html", min, bytes.NewBuffer(b)); err != nil {
		return "", err
	}
	return min.String(), nil
}

func copyFields(to, from map[string]interface{}, fields []string) {
	for _, name := range fields {
		if value := from[name]; value != nil {
			to[name] = value
		}
	}
}

func makeJSONLD(seoTag map[string]interface{}) interface{} {
	jsonLD := map[string]interface{}{
		// TODO dateModified, datePublished, publisher, mainEntityOfPage
		"@context":    "http://schema.org",
		"@type":       "WebPage", // FIXME this is BlogPosting for a blog page
		"headline":    seoTag["page_title"],
		"description": seoTag["description"],
		"url":         seoTag["canonical_url"],
	}
	if author := seoTag["author"]; author != nil {
		if m, ok := author.(map[string]interface{}); ok {
			author = m["name"]
		}
		jsonLD["author"] = map[string]interface{}{
			"@type": "Person",
			"name":  author,
		}
	}
	return jsonLD
}

// This is a separate template so it isn't minimized away.
var seoTagTemplate = template.Must(template.New("SEO tag").Parse(
	`<!-- Begin Jekyll SEO tag -->
{{.TagBody}}
<!-- End Jekyll SEO tag -->`))

// Taken verbatim from https://github.com/jekyll/jekyll-seo-tag/
// Adapted from github.com/jekyll/jekyll-seo-tag. Used according to the MIT License.
const seoTagTemplateSource = `{% if seo_tag.title? %}
  <title>{{ seo_tag.title }}</title>
{% endif %}

{% if seo_tag.page_title %}
  <meta property="og:title" content="{{ seo_tag.page_title }}" />
{% endif %}

{% if seo_tag.author.name %}
  <meta name="author" content="{{ seo_tag.author.name }}" />
{% endif %}

<meta property="og:locale" content="{{ seo_tag.page_lang | replace:'-','_' }}" />

{% if seo_tag.description %}
  <meta name="description" content="{{ seo_tag.description }}" />
  <meta property="og:description" content="{{ seo_tag.description }}" />
{% endif %}

{% if site.url %}
  <link rel="canonical" href="{{ seo_tag.canonical_url }}" />
  <meta property="og:url" content="{{ seo_tag.canonical_url }}" />
{% endif %}

{% if seo_tag.site_title %}
  <meta property="og:site_name" content="{{ seo_tag.site_title }}" />
{% endif %}

{% if seo_tag.image %}
  <meta property="og:image" content="{{ seo_tag.image.path }}" />
  {% if seo_tag.image.height %}
    <meta property="og:image:height" content="{{ seo_tag.image.height }}" />
  {% endif %}
  {% if seo_tag.image.width %}
    <meta property="og:image:width" content="{{ seo_tag.image.width }}" />
  {% endif %}
{% endif %}

{% if page.date %}
  <meta property="og:type" content="article" />
  <meta property="article:published_time" content="{{ page.date | date_to_xmlschema }}" />
{% endif %}

{% if paginator.previous_page %}
  <link rel="prev" href="{{ paginator.previous_page_path | absolute_url }}">
{% endif %}
{% if paginator.next_page %}
  <link rel="next" href="{{ paginator.next_page_path | absolute_url }}">
{% endif %}

{% if site.twitter %}
  {% if seo_tag.image %}
    <meta name="twitter:card" content="summary_large_image" />
  {% else %}
    <meta name="twitter:card" content="summary" />
  {% endif %}

  <meta name="twitter:site" content="@{{ site.twitter.username | replace:"@","" }}" />

  {% if seo_tag.author.twitter %}
    <meta name="twitter:creator" content="@{{ seo_tag.author.twitter }}" />
  {% endif %}
{% endif %}

{% if site.facebook %}
  {% if site.facebook.admins %}
    <meta property="fb:admins" content="{{ site.facebook.admins }}" />
  {% endif %}

  {% if site.facebook.publisher %}
    <meta property="article:publisher" content="{{ site.facebook.publisher }}" />
  {% endif %}

  {% if site.facebook.app_id %}
    <meta property="fb:app_id" content="{{ site.facebook.app_id }}" />
  {% endif %}
{% endif %}

{% if site.webmaster_verifications %}
  {% if site.webmaster_verifications.google %}
    <meta name="google-site-verification" content="{{ site.webmaster_verifications.google }}">
  {% endif %}

  {% if site.webmaster_verifications.bing %}
    <meta name="msvalidate.01" content="{{ site.webmaster_verifications.bing }}">
  {% endif %}

  {% if site.webmaster_verifications.alexa %}
    <meta name="alexaVerifyID" content="{{ site.webmaster_verifications.alexa }}">
  {% endif %}

  {% if site.webmaster_verifications.yandex %}
    <meta name="yandex-verification" content="{{ site.webmaster_verifications.yandex }}">
  {% endif %}
{% elsif site.google_site_verification %}
  <meta name="google-site-verification" content="{{ site.google_site_verification }}" />
{% endif %}

<script type="application/ld+json">
  {{ seo_tag.json_ld | jsonify }}
</script>`
<commit_msg>IterationKeyedMap straggler<commit_after>package plugins

import (
	"bytes"
	"fmt"
	"text/template"

	"github.com/osteele/gojekyll/utils"
	"github.com/osteele/liquid"
	"github.com/osteele/liquid/render"
	"github.com/osteele/liquid/tags"
	"github.com/tdewolff/minify"
	"github.com/tdewolff/minify/html"
)

type jekyllSEOTagPlugin struct {
	plugin
	site Site
	tpl  *liquid.Template
}

func init() {
	register("jekyll-seo-tag", &jekyllSEOTagPlugin{})
}

func (p *jekyllSEOTagPlugin) Initialize(s Site) error {
	p.site = s
	return nil
}

func (p *jekyllSEOTagPlugin) ConfigureTemplateEngine(e *liquid.Engine) error {
	e.RegisterTag("seo", p.seoTag)
	tpl, err := e.ParseTemplate([]byte(seoTagTemplateSource))
	if err != nil {
		panic(err)
	}
	p.tpl = tpl
	return nil
}

func (p *jekyllSEOTagPlugin) seoTag(ctx render.Context) (string, error) {
	buf := new(bytes.Buffer)
	e := seoTagTemplate.Execute(buf, seoTag{p.tpl, ctx})
	return buf.String(), e
}

type seoTag struct {
	tpl *liquid.Template
	ctx render.Context
}

var seoSiteFields = []string{"url", "twitter", "facebook", "logo", "social", "google_site_verification", "lang"}
var seoPageOrSiteFields = []string{"author", "description", "image", "author", "lang"}

func (p seoTag) TagBody() (string, error) {
	var (
		ctx          = p.ctx
		site         = liquid.FromDrop(ctx.Get("site")).(map[string]interface{})
		page         = liquid.FromDrop(ctx.Get("page")).(tags.IterationKeyedMap)
		pageTitle    = page["title"]
		siteTitle    = site["title"]
		canonicalURL = fmt.Sprintf("%s%s", site["url"], page["url"])
	)
	if siteTitle == nil {
		siteTitle = site["name"]
	}
	seoTag := map[string]interface{}{
		"title?": true,
		"title":  siteTitle,
		// the following are not doc'ed, but evident from inspection:
		// FIXME canonical w|w/out site.url and site.prefix
		"canonical_url": canonicalURL,
		"page_lang":     "en_US",
		"page_title":    pageTitle,
		"site_title":    siteTitle,
	}
	copyFields(seoTag, site, append(seoSiteFields, seoPageOrSiteFields...))
	copyFields(seoTag, page, seoPageOrSiteFields)
	// seoTag["description"] = page["excerpt"] FIXME appears to behave something like following, but excerpt should not be processed
	if pageTitle != nil && siteTitle != nil && pageTitle != siteTitle {
		seoTag["title"] = fmt.Sprintf("%s | %s", pageTitle, siteTitle)
	}
	if author, ok := seoTag["author"].(string); ok {
		if data, _ := utils.FollowDots(site, []string{"data", "authors", author}); data != nil {
			seoTag["author"] = data
		}
	}
	seoTag["json_ld"] = makeJSONLD(seoTag)
	bindings := map[string]interface{}{
		"page":    page,
		"site":    site,
		"seo_tag": seoTag,
	}
	b, err := p.tpl.Render(bindings)
	if err != nil {
		return "", err
	}
	m := minify.New()
	m.AddFunc("text/html", html.Minify)
	min := bytes.NewBuffer(make([]byte, 0, len(b)))
	if err := m.Minify("text/html", min, bytes.NewBuffer(b)); err != nil {
		return "", err
	}
	return min.String(), nil
}

func copyFields(to, from map[string]interface{}, fields []string) {
	for _, name := range fields {
		if value := from[name]; value != nil {
			to[name] = value
		}
	}
}

func makeJSONLD(seoTag map[string]interface{}) interface{} {
	jsonLD := map[string]interface{}{
		// TODO dateModified, datePublished, publisher, mainEntityOfPage
		"@context":    "http://schema.org",
		"@type":       "WebPage", // FIXME this is BlogPosting for a blog page
		"headline":    seoTag["page_title"],
		"description": seoTag["description"],
		"url":         seoTag["canonical_url"],
	}
	if author := seoTag["author"]; author != nil {
		if m, ok := author.(map[string]interface{}); ok {
			author = m["name"]
		}
		jsonLD["author"] = map[string]interface{}{
			"@type": "Person",
			"name":  author,
		}
	}
	return jsonLD
}

// This is a separate template so it isn't minimized away.
var seoTagTemplate = template.Must(template.New("SEO tag").Parse(
	`<!-- Begin Jekyll SEO tag -->
{{.TagBody}}
<!-- End Jekyll SEO tag -->`))

// Taken verbatim from https://github.com/jekyll/jekyll-seo-tag/
// Adapted from github.com/jekyll/jekyll-seo-tag. Used according to the MIT License.
const seoTagTemplateSource = `{% if seo_tag.title? %}
  <title>{{ seo_tag.title }}</title>
{% endif %}

{% if seo_tag.page_title %}
  <meta property="og:title" content="{{ seo_tag.page_title }}" />
{% endif %}

{% if seo_tag.author.name %}
  <meta name="author" content="{{ seo_tag.author.name }}" />
{% endif %}

<meta property="og:locale" content="{{ seo_tag.page_lang | replace:'-','_' }}" />

{% if seo_tag.description %}
  <meta name="description" content="{{ seo_tag.description }}" />
  <meta property="og:description" content="{{ seo_tag.description }}" />
{% endif %}

{% if site.url %}
  <link rel="canonical" href="{{ seo_tag.canonical_url }}" />
  <meta property="og:url" content="{{ seo_tag.canonical_url }}" />
{% endif %}

{% if seo_tag.site_title %}
  <meta property="og:site_name" content="{{ seo_tag.site_title }}" />
{% endif %}

{% if seo_tag.image %}
  <meta property="og:image" content="{{ seo_tag.image.path }}" />
  {% if seo_tag.image.height %}
    <meta property="og:image:height" content="{{ seo_tag.image.height }}" />
  {% endif %}
  {% if seo_tag.image.width %}
    <meta property="og:image:width" content="{{ seo_tag.image.width }}" />
  {% endif %}
{% endif %}

{% if page.date %}
  <meta property="og:type" content="article" />
  <meta property="article:published_time" content="{{ page.date | date_to_xmlschema }}" />
{% endif %}

{% if paginator.previous_page %}
  <link rel="prev" href="{{ paginator.previous_page_path | absolute_url }}">
{% endif %}
{% if paginator.next_page %}
  <link rel="next" href="{{ paginator.next_page_path | absolute_url }}">
{% endif %}

{% if site.twitter %}
  {% if seo_tag.image %}
    <meta name="twitter:card" content="summary_large_image" />
  {% else %}
    <meta name="twitter:card" content="summary" />
  {% endif %}

  <meta name="twitter:site" content="@{{ site.twitter.username | replace:"@","" }}" />

  {% if seo_tag.author.twitter %}
    <meta name="twitter:creator" content="@{{ seo_tag.author.twitter }}" />
  {% endif %}
{% endif %}

{% if site.facebook %}
  {% if site.facebook.admins %}
    <meta property="fb:admins" content="{{ site.facebook.admins }}" />
  {% endif %}

  {% if site.facebook.publisher %}
    <meta property="article:publisher" content="{{ site.facebook.publisher }}" />
  {% endif %}

  {% if site.facebook.app_id %}
    <meta property="fb:app_id" content="{{ site.facebook.app_id }}" />
  {% endif %}
{% endif %}

{% if site.webmaster_verifications %}
  {% if site.webmaster_verifications.google %}
    <meta name="google-site-verification" content="{{ site.webmaster_verifications.google }}">
  {% endif %}

  {% if site.webmaster_verifications.bing %}
    <meta name="msvalidate.01" content="{{ site.webmaster_verifications.bing }}">
  {% endif %}

  {% if site.webmaster_verifications.alexa %}
    <meta name="alexaVerifyID" content="{{ site.webmaster_verifications.alexa }}">
  {% endif %}

  {% if site.webmaster_verifications.yandex %}
    <meta name="yandex-verification" content="{{ site.webmaster_verifications.yandex }}">
  {% endif %}
{% elsif site.google_site_verification %}
  <meta name="google-site-verification" content="{{ site.google_site_verification }}" />
{% endif %}

<script type="application/ld+json">
  {{ seo_tag.json_ld | jsonify }}
</script>`
<|endoftext|>


<commit_before>package rounding

import (
	"math/big"
	"math/rand"
	"testing"
)

func TestRoundUp(t *testing.T) {
	m := Up
	testRounding(t, "5.5", "6", 0, m)
	testRounding(t, "2.5", "3", 0, m)
	testRounding(t, "1.6", "2", 0, m)
	testRounding(t, "1.1", "2", 0, m)
	testRounding(t, "1.0", "1", 0, m)
	testRounding(t, "-1.0", "-1", 0, m)
	testRounding(t, "-1.1", "-2", 0, m)
	testRounding(t, "-1.6", "-2", 0, m)
	testRounding(t, "-2.5", "-3", 0, m)
	testRounding(t, "-5.5", "-6", 0, m)

	testRounding(t, "0", "0", 0, m)
	testRounding(t, "0.01", "1", 0, m)
	testRounding(t, "1.01", "2", 0, m)
	testRounding(t, "-0.01", "-1", 0, m)
	testRounding(t, "-1.01", "-2", 0, m)
}

func TestRoundDown(t *testing.T) {
	m := Down
	testRounding(t, "5.5", "5", 0, m)
	testRounding(t, "2.5", "2", 0, m)
	testRounding(t, "1.6", "1", 0, m)
	testRounding(t, "1.1", "1", 0, m)
	testRounding(t, "1.0", "1", 0, m)
	testRounding(t, "-1.0", "-1", 0, m)
	testRounding(t, "-1.1", "-1", 0, m)
	testRounding(t, "-1.6", "-1", 0, m)
	testRounding(t, "-2.5", "-2", 0, m)
	testRounding(t, "-5.5", "-5", 0, m)

	testRounding(t, "0", "0", 0, m)
	testRounding(t, "0.01", "0", 0, m)
	testRounding(t, "1.01", "1", 0, m)
	testRounding(t, "-0.01", "0", 0, m)
	testRounding(t, "-1.01", "-1", 0, m)
}

func TestRoundCeil(t *testing.T) {
	m := Ceil
	testRounding(t, "5.5", "6", 0, m)
	testRounding(t, "2.5", "3", 0, m)
	testRounding(t, "1.6", "2", 0, m)
	testRounding(t, "1.1", "2", 0, m)
	testRounding(t, "1.0", "1", 0, m)
	testRounding(t, "-1.0", "-1", 0, m)
	testRounding(t, "-1.1", "-1", 0, m)
	testRounding(t, "-1.6", "-1", 0, m)
	testRounding(t, "-2.5", "-2", 0, m)
	testRounding(t, "-5.5", "-5", 0, m)

	testRounding(t, "0", "0", 0, m)
	testRounding(t, "0.01", "1", 0, m)
	testRounding(t, "1.01", "2", 0, m)
	testRounding(t, "-0.01", "0", 0, m)
	testRounding(t, "-1.01", "-1", 0, m)
}

func TestRoundFloor(t *testing.T) {
	m := Floor
	testRounding(t, "5.5", "5", 0, m)
	testRounding(t, "2.5", "2", 0, m)
	testRounding(t, "1.6", "1", 0, m)
	testRounding(t, "1.1", "1", 0, m)
	testRounding(t, "1.0", "1", 0, m)
	testRounding(t, "-1.0", "-1", 0, m)
	testRounding(t, "-1.1", "-2", 0, m)
	testRounding(t, "-1.6", "-2", 0, m)
	testRounding(t, "-2.5", "-3", 0, m)
	testRounding(t, "-5.5", "-6", 0, m)

	testRounding(t, "0", "0", 0, m)
	testRounding(t, "0.01", "0", 0, m)
	testRounding(t, "1.01", "1", 0, m)
	testRounding(t, "-0.01", "-1", 0, m)
	testRounding(t, "-1.01", "-2", 0, m)
}

func TestRoundHalfUp(t *testing.T) {
	m := HalfUp
	testRounding(t, "5.5", "6", 0, m)
	testRounding(t, "5.51", "6", 0, m)
	testRounding(t, "5.5001", "6", 0, m)
	testRounding(t, "5.4999", "5", 0, m)
	testRounding(t, "2.5", "3", 0, m)
	testRounding(t, "1.6", "2", 0, m)
	testRounding(t, "1.1", "1", 0, m)
	testRounding(t, "1.0", "1", 0, m)
	testRounding(t, "-1.0", "-1", 0, m)
	testRounding(t, "-1.1", "-1", 0, m)
	testRounding(t, "-1.6", "-2", 0, m)
	testRounding(t, "-2.5", "-3", 0, m)
	testRounding(t, "-5.5", "-6", 0, m)
	testRounding(t, "-5.51", "-6", 0, m)
	testRounding(t, "-5.5001", "-6", 0, m)
	testRounding(t, "-5.4999", "-5", 0, m)

	testRounding(t, "0", "0", 0, m)
	testRounding(t, "0.01", "0", 0, m)
	testRounding(t, "1.01", "1", 0, m)
	testRounding(t, "-0.01", "0", 0, m)
	testRounding(t, "-1.01", "-1", 0, m)
}

func TestRoundHalfDown(t *testing.T) {
	m := HalfDown
	testRounding(t, "5.5", "5", 0, m)
	testRounding(t, "5.51", "6", 0, m)
	testRounding(t, "5.5001", "6", 0, m)
	testRounding(t, "5.4999", "5", 0, m)
	testRounding(t, "2.5", "2", 0, m)
	testRounding(t, "1.6", "2", 0, m)
	testRounding(t, "1.1", "1", 0, m)
	testRounding(t, "1.0", "1", 0, m)
	testRounding(t, "-1.0", "-1", 0, m)
	testRounding(t, "-1.1", "-1", 0, m)
	testRounding(t, "-1.6", "-2", 0, m)
	testRounding(t, "-2.5", "-2", 0, m)
	testRounding(t, "-5.5", "-5", 0, m)
	testRounding(t, "-5.51", "-6", 0, m)
	testRounding(t, "-5.5001", "-6", 0, m)
	testRounding(t, "-5.4999", "-5", 0, m)

	testRounding(t, "0", "0", 0, m)
	testRounding(t, "0.01", "0", 0, m)
	testRounding(t, "1.01", "1", 0, m)
	testRounding(t, "-0.01", "0", 0, m)
	testRounding(t, "-1.01", "-1", 0, m)
}

func TestRoundHalfEven(t *testing.T) {
	m := HalfEven
	testRounding(t, "5.5", "6", 0, m)
	testRounding(t, "5.51", "6", 0, m)
	testRounding(t, "5.5001", "6", 0, m)
	testRounding(t, "5.4999", "5", 0, m)
	testRounding(t, "6.51", "7", 0, m)
	testRounding(t, "6.5001", "7", 0, m)
	testRounding(t, "6.4999", "6", 0, m)

	testRounding(t, "2.5", "2", 0, m)
	testRounding(t, "1.6", "2", 0, m)
	testRounding(t, "1.1", "1", 0, m)
	testRounding(t, "1.0", "1", 0, m)
	testRounding(t, "-1.0", "-1", 0, m)
	testRounding(t, "-1.1", "-1", 0, m)
	testRounding(t, "-1.6", "-2", 0, m)
	testRounding(t, "-2.5", "-2", 0, m)
	testRounding(t, "-5.5", "-6", 0, m)
	testRounding(t, "-5.51", "-6", 0, m)
	testRounding(t, "-5.5001", "-6", 0, m)
	testRounding(t, "-5.4999", "-5", 0, m)
	testRounding(t, "-6.51", "-7", 0, m)
	testRounding(t, "-6.5001", "-7", 0, m)
	testRounding(t, "-6.4999", "-6", 0, m)

	testRounding(t, "0", "0", 0, m)
	testRounding(t, "0.01", "0", 0, m)
	testRounding(t, "1.01", "1", 0, m)
	testRounding(t, "-0.01", "0", 0, m)
	testRounding(t, "-1.01", "-1", 0, m)
}

func testRounding(t *testing.T, a, b string, prec int, method RoundingMode) {
	x, ok := new(big.Rat).SetString(a)
	if !ok {
		t.Fatalf("Failed to parse: %s", a)
	}
	y, ok := new(big.Rat).SetString(b)
	if !ok {
		t.Fatalf("Failed to parse: %s", b)
	}

	Round(x, prec, method)

	if x.Cmp(y) != 0 {
		t.Errorf("test Round(%v, %v, %v) == %s. Got %v", a, prec, method, y, x)
	}
}

func BenchmarkRoundUp(b *testing.B) {
	benchmarkRounding(b, Up)
}

func BenchmarkRoundHalfEven(b *testing.B) {
	benchmarkRounding(b, HalfEven)
}

func benchmarkRounding(b *testing.B, mode RoundingMode) {
	r := rand.New(rand.NewSource(rand.Int63()))
	x := new(big.Rat)
	d := big.NewInt(1e10)
	for i := 0; i < b.N; i++ {
		b.StopTimer()
		x.SetFrac(x.Num().Rand(r, d), d)
		if i%2 == 0 {
			x.Neg(x)
		}
		prec := rand.Intn(10)
		b.StartTimer()

		Round(x, prec, mode)
	}
}
<commit_msg>Better test printing (#9)<commit_after>package rounding

import (
	"math/big"
	"math/rand"
	"testing"
)

func TestRoundUp(t *testing.T) {
	m := Up
	testRounding(t, "5.5", "6", 0, m)
	testRounding(t, "2.5", "3", 0, m)
	testRounding(t, "1.6", "2", 0, m)
	testRounding(t, "1.1", "2", 0, m)
	testRounding(t, "1.0", "1", 0, m)
	testRounding(t, "-1.0", "-1", 0, m)
	testRounding(t, "-1.1", "-2", 0, m)
	testRounding(t, "-1.6", "-2", 0, m)
	testRounding(t, "-2.5", "-3", 0, m)
	testRounding(t, "-5.5", "-6", 0, m)

	testRounding(t, "0", "0", 0, m)
	testRounding(t, "0.01", "1", 0, m)
	testRounding(t, "1.01", "2", 0, m)
	testRounding(t, "-0.01", "-1", 0, m)
	testRounding(t, "-1.01", "-2", 0, m)
}

func TestRoundDown(t *testing.T) {
	m := Down
	testRounding(t, "5.5", "5", 0, m)
	testRounding(t, "2.5", "2", 0, m)
	testRounding(t, "1.6", "1", 0, m)
	testRounding(t, "1.1", "1", 0, m)
	testRounding(t, "1.0", "1", 0, m)
	testRounding(t, "-1.0", "-1", 0, m)
	testRounding(t, "-1.1", "-1", 0, m)
	testRounding(t, "-1.6", "-1", 0, m)
	testRounding(t, "-2.5", "-2", 0, m)
	testRounding(t, "-5.5", "-5", 0, m)

	testRounding(t, "0", "0", 0, m)
	testRounding(t, "0.01", "0", 0, m)
	testRounding(t, "1.01", "1", 0, m)
	testRounding(t, "-0.01", "0", 0, m)
	testRounding(t, "-1.01", "-1", 0, m)
}

func TestRoundCeil(t *testing.T) {
	m := Ceil
	testRounding(t, "5.5", "6", 0, m)
	testRounding(t, "2.5", "3", 0, m)
	testRounding(t, "1.6", "2", 0, m)
	testRounding(t, "1.1", "2", 0, m)
	testRounding(t, "1.0", "1", 0, m)
	testRounding(t, "-1.0", "-1", 0, m)
	testRounding(t, "-1.1", "-1", 0, m)
	testRounding(t, "-1.6", "-1", 0, m)
	testRounding(t, "-2.5", "-2", 0, m)
	testRounding(t, "-5.5", "-5", 0, m)

	testRounding(t, "0", "0", 0, m)
	testRounding(t, "0.01", "1", 0, m)
	testRounding(t, "1.01", "2", 0, m)
	testRounding(t, "-0.01", "0", 0, m)
	testRounding(t, "-1.01", "-1", 0, m)
}

func TestRoundFloor(t *testing.T) {
	m := Floor
	testRounding(t, "5.5", "5", 0, m)
	testRounding(t, "2.5", "2", 0, m)
	testRounding(t, "1.6", "1", 0, m)
	testRounding(t, "1.1", "1", 0, m)
	testRounding(t, "1.0", "1", 0, m)
	testRounding(t, "-1.0", "-1", 0, m)
	testRounding(t, "-1.1", "-2", 0, m)
	testRounding(t, "-1.6", "-2", 0, m)
	testRounding(t, "-2.5", "-3", 0, m)
	testRounding(t, "-5.5", "-6", 0, m)

	testRounding(t, "0", "0", 0, m)
	testRounding(t, "0.01", "0", 0, m)
	testRounding(t, "1.01", "1", 0, m)
	testRounding(t, "-0.01", "-1", 0, m)
	testRounding(t, "-1.01", "-2", 0, m)
}

func TestRoundHalfUp(t *testing.T) {
	m := HalfUp
	testRounding(t, "5.5", "6", 0, m)
	testRounding(t, "5.51", "6", 0, m)
	testRounding(t, "5.5001", "6", 0, m)
	testRounding(t, "5.4999", "5", 0, m)
	testRounding(t, "2.5", "3", 0, m)
	testRounding(t, "1.6", "2", 0, m)
	testRounding(t, "1.1", "1", 0, m)
	testRounding(t, "1.0", "1", 0, m)
	testRounding(t, "-1.0", "-1", 0, m)
	testRounding(t, "-1.1", "-1", 0, m)
	testRounding(t, "-1.6", "-2", 0, m)
	testRounding(t, "-2.5", "-3", 0, m)
	testRounding(t, "-5.5", "-6", 0, m)
	testRounding(t, "-5.51", "-6", 0, m)
	testRounding(t, "-5.5001", "-6", 0, m)
	testRounding(t, "-5.4999", "-5", 0, m)

	testRounding(t, "0", "0", 0, m)
	testRounding(t, "0.01", "0", 0, m)
	testRounding(t, "1.01", "1", 0, m)
	testRounding(t, "-0.01", "0", 0, m)
	testRounding(t, "-1.01", "-1", 0, m)
}

func TestRoundHalfDown(t *testing.T) {
	m := HalfDown
	testRounding(t, "5.5", "5", 0, m)
	testRounding(t, "5.51", "6", 0, m)
	testRounding(t, "5.5001", "6", 0, m)
	testRounding(t, "5.4999", "5", 0, m)
	testRounding(t, "2.5", "2", 0, m)
	testRounding(t, "1.6", "2", 0, m)
	testRounding(t, "1.1", "1", 0, m)
	testRounding(t, "1.0", "1", 0, m)
	testRounding(t, "-1.0", "-1", 0, m)
	testRounding(t, "-1.1", "-1", 0, m)
	testRounding(t, "-1.6", "-2", 0, m)
	testRounding(t, "-2.5", "-2", 0, m)
	testRounding(t, "-5.5", "-5", 0, m)
	testRounding(t, "-5.51", "-6", 0, m)
	testRounding(t, "-5.5001", "-6", 0, m)
	testRounding(t, "-5.4999", "-5", 0, m)

	testRounding(t, "0", "0", 0, m)
	testRounding(t, "0.01", "0", 0, m)
	testRounding(t, "1.01", "1", 0, m)
	testRounding(t, "-0.01", "0", 0, m)
	testRounding(t, "-1.01", "-1", 0, m)
}

func TestRoundHalfEven(t *testing.T) {
	m := HalfEven
	testRounding(t, "5.5", "6", 0, m)
	testRounding(t, "5.51", "6", 0, m)
	testRounding(t, "5.5001", "6", 0, m)
	testRounding(t, "5.4999", "5", 0, m)
	testRounding(t, "6.51", "7", 0, m)
	testRounding(t, "6.5001", "7", 0, m)
	testRounding(t, "6.4999", "6", 0, m)

	testRounding(t, "2.5", "2", 0, m)
	testRounding(t, "1.6", "2", 0, m)
	testRounding(t, "1.1", "1", 0, m)
	testRounding(t, "1.0", "1", 0, m)
	testRounding(t, "-1.0", "-1", 0, m)
	testRounding(t, "-1.1", "-1", 0, m)
	testRounding(t, "-1.6", "-2", 0, m)
	testRounding(t, "-2.5", "-2", 0, m)
	testRounding(t, "-5.5", "-6", 0, m)
	testRounding(t, "-5.51", "-6", 0, m)
	testRounding(t, "-5.5001", "-6", 0, m)
	testRounding(t, "-5.4999", "-5", 0, m)
	testRounding(t, "-6.51", "-7", 0, m)
	testRounding(t, "-6.5001", "-7", 0, m)
	testRounding(t, "-6.4999", "-6", 0, m)

	testRounding(t, "0", "0", 0, m)
	testRounding(t, "0.01", "0", 0, m)
	testRounding(t, "1.01", "1", 0, m)
	testRounding(t, "-0.01", "0", 0, m)
	testRounding(t, "-1.01", "-1", 0, m)
}

func testRounding(t *testing.T, a, b string, prec int, method RoundingMode) {
	x, ok := new(big.Rat).SetString(a)
	if !ok {
		t.Fatalf("Failed to parse: %s", a)
	}
	y, ok := new(big.Rat).SetString(b)
	if !ok {
		t.Fatalf("Failed to parse: %s", b)
	}

	Round(x, prec, method)

	if x.Cmp(y) != 0 {
		t.Errorf("test Round(%v, %v, %v) == %s. Got %v", a, prec, method, y.FloatString(3), x.FloatString(3))
	}
}

func BenchmarkRoundUp(b *testing.B) {
	benchmarkRounding(b, Up)
}

func BenchmarkRoundHalfEven(b *testing.B) {
	benchmarkRounding(b, HalfEven)
}

func benchmarkRounding(b *testing.B, mode RoundingMode) {
	r := rand.New(rand.NewSource(rand.Int63()))
	x := new(big.Rat)
	d := big.NewInt(1e10)
	for i := 0; i < b.N; i++ {
		b.StopTimer()
		x.SetFrac(x.Num().Rand(r, d), d)
		if i%2 == 0 {
			x.Neg(x)
		}
		prec := rand.Intn(10)
		b.StartTimer()

		Round(x, prec, mode)
	}
}
<|endoftext|>


<commit_before>package pty

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"os/exec"
	"syscall"
	"time"
)

var (
	stdout bytes.Buffer
)

// Start assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout,
// and c.Stderr, calls c.Start, and returns the File of the tty's
// corresponding pty.
func Start(c *exec.Cmd) (term *Terminal, err error) {
	if term, err = NewTerminal(); err != nil {
		return nil, err
	}
	return term, term.Start(c)
}

func (t *Terminal) Start(c *exec.Cmd) (err error) {
	if t == nil {
		return errors.New("terminal not assigned.")
	}

	c.Stdout = bufio.NewWriter(&stdout)
	c.Stdin = t.Tty
	c.Stderr = bufio.NewWriter(&stdout)

	c.SysProcAttr = &syscall.SysProcAttr{Setctty: true, Setsid: true}
	if err = c.Start(); err != nil {
		fmt.Println("error is ", err)
		t.Pty.Close()
		return
	}

	go func() {
		for {
			time.Sleep(10)
			by, _ := stdout.ReadBytes(('\x0a' | '\x23' | '\x24' | '\x25'))

			t.Tty.Write(by)
			if t.Log != nil {
				t.Log.Write(by)
			}
		}
	}()

	return
}
<commit_msg>change stdout.ReadBytes delim<commit_after>package pty

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"os/exec"
	"syscall"
	"time"
)

var (
	stdout bytes.Buffer
)

// Start assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout,
// and c.Stderr, calls c.Start, and returns the File of the tty's
// corresponding pty.
func Start(c *exec.Cmd) (term *Terminal, err error) {
	if term, err = NewTerminal(); err != nil {
		return nil, err
	}
	return term, term.Start(c)
}

func (t *Terminal) Start(c *exec.Cmd) (err error) {
	if t == nil {
		return errors.New("terminal not assigned.")
	}

	c.Stdout = bufio.NewWriter(&stdout)
	c.Stdin = t.Tty
	c.Stderr = bufio.NewWriter(&stdout)

	c.SysProcAttr = &syscall.SysProcAttr{Setctty: true, Setsid: true}
	if err = c.Start(); err != nil {
		fmt.Println("error is ", err)
		t.Pty.Close()
		return
	}

	go func() {
		for {
			time.Sleep(10)
			by, _ := stdout.ReadBytes(('\x0a' | '\x23' | '\x24' | '\x25' | '\x22' | '\x27' | '\x7b' | '\x7d'))

			t.Tty.Write(by)
			if t.Log != nil {
				t.Log.Write(by)
			}
		}
	}()

	return
}
<|endoftext|>


<commit_before>package utils

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"github.com/jvgutierrez/db44monitor/monitor"
)

type OutputHandler struct {
	measures []monitor.Measure
	Output   string
	c        int
}

func (oh *OutputHandler) FlushMeasures() {
	log.Println("Flushing measures")

	j, err := json.Marshal(oh.measures)
	if err != nil {
		log.Fatalf("Unable to marshal measures into JSON: %v", err)
	}
	ioutil.WriteFile(fmt.Sprintf("%s.%d", oh.Output, oh.c/10), j, 0644)
	oh.measures = []monitor.Measure{}
}

func (oh *OutputHandler) ConsolidateOutputs() {
	log.Println("Consolidating outputs...")
	measures := []monitor.Measure{}
	files, err := filepath.Glob(filepath.Join(filepath.Dir(oh.Output), fmt.Sprintf("%s%s", filepath.Base(oh.Output), ".*")))
	if err != nil {
		log.Fatalf("unable to list output files: %v", err)
	}
	for _, fileName := range files {
		data, err := ioutil.ReadFile(fileName)
		if err != nil {
			log.Fatalf("Unable to read previously generated output: %v", err)
		}
		chunk := []monitor.Measure{}
		err = json.Unmarshal(data, &chunk)
		if err != nil {
			log.Fatalf("Unable to read previously generated output: %v", err)
		}
		measures = append(measures, chunk...)
	}

	data, err := json.Marshal(measures)
	if err != nil {
		log.Fatalf("Unable to marshal measures: %v", err)
	}
	ioutil.WriteFile(oh.Output, data, 0644)
	if err != nil {
		log.Fatalf("Unable to write output file: %v", err)
	}
	for _, fileName := range files {
		err = os.Remove(fileName)
		if err != nil {
			log.Fatalf("Unable to delete temp file: %v", err)
		}
	}
}

func (oh *OutputHandler) AddMeasure(m monitor.Measure) {
	oh.measures = append(oh.measures, m)
	oh.c++
	if oh.c%10 == 0 {
		oh.FlushMeasures()
	}
}
<commit_msg>flush every 100 measures<commit_after>package utils

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"github.com/jvgutierrez/db44monitor/monitor"
)

type OutputHandler struct {
	measures []monitor.Measure
	Output   string
	c        int
}

func (oh *OutputHandler) FlushMeasures() {
	log.Println("Flushing measures")

	j, err := json.Marshal(oh.measures)
	if err != nil {
		log.Fatalf("Unable to marshal measures into JSON: %v", err)
	}
	ioutil.WriteFile(fmt.Sprintf("%s.%d", oh.Output, oh.c/10), j, 0644)
	oh.measures = []monitor.Measure{}
}

func (oh *OutputHandler) ConsolidateOutputs() {
	log.Println("Consolidating outputs...")
	measures := []monitor.Measure{}
	files, err := filepath.Glob(filepath.Join(filepath.Dir(oh.Output), fmt.Sprintf("%s%s", filepath.Base(oh.Output), ".*")))
	if err != nil {
		log.Fatalf("unable to list output files: %v", err)
	}
	for _, fileName := range files {
		data, err := ioutil.ReadFile(fileName)
		if err != nil {
			log.Fatalf("Unable to read previously generated output: %v", err)
		}
		chunk := []monitor.Measure{}
		err = json.Unmarshal(data, &chunk)
		if err != nil {
			log.Fatalf("Unable to read previously generated output: %v", err)
		}
		measures = append(measures, chunk...)
	}

	data, err := json.Marshal(measures)
	if err != nil {
		log.Fatalf("Unable to marshal measures: %v", err)
	}
	ioutil.WriteFile(oh.Output, data, 0644)
	if err != nil {
		log.Fatalf("Unable to write output file: %v", err)
	}
	for _, fileName := range files {
		err = os.Remove(fileName)
		if err != nil {
			log.Fatalf("Unable to delete temp file: %v", err)
		}
	}
}

func (oh *OutputHandler) AddMeasure(m monitor.Measure) {
	oh.measures = append(oh.measures, m)
	oh.c++
	if oh.c%100 == 0 {
		oh.FlushMeasures()
	}
}
<|endoftext|>


<commit_before>package b2

import (
	"bytes"
	"crypto/sha1"
	"encoding/hex"
	"encoding/json"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
)

// Upload uploads a file to a B2 bucket. If mimeType is "", "b2/x-auto" will be used.
//
// Concurrent calls to Upload will use separate upload URLs, but consequent ones
// will attempt to reuse previously obtained ones to save b2_get_upload_url calls.
// Upload URL failures are handled transparently.
//
// Since the B2 API requires a SHA1 header, normally the file will first be read
// entirely into a memory buffer. Two cases avoid the memory copy: if r is a
// bytes.Buffer, the SHA1 will be computed in place; otherwise, if r implements io.Seeker
// (like *os.File and *bytes.Reader), the file will be read twice, once to compute
// the SHA1 and once to upload.
//
// If a file by this name already exist, a new version will be created.
func (b *Bucket) Upload(r io.Reader, name, mimeType string) (*FileInfo, error) {
	var body io.ReadSeeker
	switch r := r.(type) {
	case *bytes.Buffer:
		defer r.Reset() // we are expected to consume it
		body = bytes.NewReader(r.Bytes())
	case io.ReadSeeker:
		body = r
	default:
		b, err := ioutil.ReadAll(r)
		if err != nil {
			return nil, err
		}
		body = bytes.NewReader(b)
	}

	h := sha1.New()
	length, err := io.Copy(h, body)
	if err != nil {
		return nil, err
	}
	sha1Sum := hex.EncodeToString(h.Sum(nil))

	var fi *FileInfo
	for i := 0; i < 5; i++ {
		if _, err = body.Seek(0, io.SeekStart); err != nil {
			return nil, err
		}

		fi, err = b.UploadWithSHA1(body, name, mimeType, sha1Sum, int(length))
		if err == nil {
			break
		}
	}
	return fi, err
}

type uploadURL struct {
	UploadURL, AuthorizationToken string
}

func (b *Bucket) getUploadURL() (u *uploadURL, err error) {
	b.uploadURLsMu.Lock()
	if len(b.uploadURLs) > 0 {
		u = b.uploadURLs[len(b.uploadURLs)-1]
		b.uploadURLs = b.uploadURLs[:len(b.uploadURLs)-1]
	}
	b.uploadURLsMu.Unlock()
	if u != nil {
		return
	}

	res, err := b.c.doRequest("b2_get_upload_url", map[string]interface{}{
		"bucketId": b.ID,
	})
	if err != nil {
		return
	}
	defer drainAndClose(res.Body)
	err = json.NewDecoder(res.Body).Decode(&u)
	return
}

func (b *Bucket) putUploadURL(u *uploadURL) {
	b.uploadURLsMu.Lock()
	defer b.uploadURLsMu.Unlock()
	b.uploadURLs = append(b.uploadURLs, u)
}

// UploadWithSHA1 is like Upload, but allows the caller to specify previously
// known SHA1 and length of the file. It never does any buffering, nor does it
// retry on failure.
//
// Note that retrying on most upload failures is mandatory by the B2 API
// documentation, and not just error condition handling.
//
// sha1Sum should be the hex encoding of the SHA1 sum of what will be read from r.
//
// This is an advanced interface, most clients should use Upload, and consider
// passing it a bytes.Buffer or io.ReadSeeker to avoid buffering.
func (b *Bucket) UploadWithSHA1(r io.Reader, name, mimeType, sha1Sum string, length int) (*FileInfo, error) {
	uurl, err := b.getUploadURL()
	if err != nil {
		return nil, err
	}

	req, err := http.NewRequest("POST", uurl.UploadURL, r)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Authorization", uurl.AuthorizationToken)
	req.Header.Set("X-Bz-File-Name", url.QueryEscape(name))
	req.Header.Set("Content-Type", mimeType)
	req.Header.Set("Content-Length", strconv.Itoa(length))
	req.Header.Set("X-Bz-Content-Sha1", sha1Sum)

	res, err := b.c.hc.Do(req)
	if err != nil {
		return nil, err
	}
	if res.StatusCode != 200 {
		return nil, parseB2Error(res)
	}
	defer drainAndClose(res.Body)

	fi := fileInfoObj{}
	if err = json.NewDecoder(res.Body).Decode(&fi); err != nil {
		return nil, err
	}
	b.putUploadURL(uurl)
	return fi.makeFileInfo(), nil
}
<commit_msg>Stop net/http from closing the io.Reader on Upload<commit_after>package b2

import (
	"bytes"
	"crypto/sha1"
	"encoding/hex"
	"encoding/json"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
)

// Upload uploads a file to a B2 bucket. If mimeType is "", "b2/x-auto" will be used.
//
// Concurrent calls to Upload will use separate upload URLs, but consequent ones
// will attempt to reuse previously obtained ones to save b2_get_upload_url calls.
// Upload URL failures are handled transparently.
//
// Since the B2 API requires a SHA1 header, normally the file will first be read
// entirely into a memory buffer. Two cases avoid the memory copy: if r is a
// bytes.Buffer, the SHA1 will be computed in place; otherwise, if r implements io.Seeker
// (like *os.File and *bytes.Reader), the file will be read twice, once to compute
// the SHA1 and once to upload.
//
// If a file by this name already exist, a new version will be created.
func (b *Bucket) Upload(r io.Reader, name, mimeType string) (*FileInfo, error) {
	var body io.ReadSeeker
	switch r := r.(type) {
	case *bytes.Buffer:
		defer r.Reset() // we are expected to consume it
		body = bytes.NewReader(r.Bytes())
	case io.ReadSeeker:
		body = r
	default:
		b, err := ioutil.ReadAll(r)
		if err != nil {
			return nil, err
		}
		body = bytes.NewReader(b)
	}

	h := sha1.New()
	length, err := io.Copy(h, body)
	if err != nil {
		return nil, err
	}
	sha1Sum := hex.EncodeToString(h.Sum(nil))

	var fi *FileInfo
	for i := 0; i < 5; i++ {
		if _, err = body.Seek(0, io.SeekStart); err != nil {
			return nil, err
		}

		fi, err = b.UploadWithSHA1(body, name, mimeType, sha1Sum, int(length))
		if err == nil {
			break
		}
	}
	return fi, err
}

type uploadURL struct {
	UploadURL, AuthorizationToken string
}

func (b *Bucket) getUploadURL() (u *uploadURL, err error) {
	b.uploadURLsMu.Lock()
	if len(b.uploadURLs) > 0 {
		u = b.uploadURLs[len(b.uploadURLs)-1]
		b.uploadURLs = b.uploadURLs[:len(b.uploadURLs)-1]
	}
	b.uploadURLsMu.Unlock()
	if u != nil {
		return
	}

	res, err := b.c.doRequest("b2_get_upload_url", map[string]interface{}{
		"bucketId": b.ID,
	})
	if err != nil {
		return
	}
	defer drainAndClose(res.Body)
	err = json.NewDecoder(res.Body).Decode(&u)
	return
}

func (b *Bucket) putUploadURL(u *uploadURL) {
	b.uploadURLsMu.Lock()
	defer b.uploadURLsMu.Unlock()
	b.uploadURLs = append(b.uploadURLs, u)
}

// UploadWithSHA1 is like Upload, but allows the caller to specify previously
// known SHA1 and length of the file. It never does any buffering, nor does it
// retry on failure.
//
// Note that retrying on most upload failures is mandatory by the B2 API
// documentation, and not just error condition handling.
//
// sha1Sum should be the hex encoding of the SHA1 sum of what will be read from r.
//
// This is an advanced interface, most clients should use Upload, and consider
// passing it a bytes.Buffer or io.ReadSeeker to avoid buffering.
func (b *Bucket) UploadWithSHA1(r io.Reader, name, mimeType, sha1Sum string, length int) (*FileInfo, error) {
	uurl, err := b.getUploadURL()
	if err != nil {
		return nil, err
	}

	req, err := http.NewRequest("POST", uurl.UploadURL, ioutil.NopCloser(r))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Authorization", uurl.AuthorizationToken)
	req.Header.Set("X-Bz-File-Name", url.QueryEscape(name))
	req.Header.Set("Content-Type", mimeType)
	req.Header.Set("Content-Length", strconv.Itoa(length))
	req.Header.Set("X-Bz-Content-Sha1", sha1Sum)

	res, err := b.c.hc.Do(req)
	if err != nil {
		return nil, err
	}
	if res.StatusCode != 200 {
		return nil, parseB2Error(res)
	}
	defer drainAndClose(res.Body)

	fi := fileInfoObj{}
	if err = json.NewDecoder(res.Body).Decode(&fi); err != nil {
		return nil, err
	}
	b.putUploadURL(uurl)
	return fi.makeFileInfo(), nil
}
<|endoftext|>


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

// Modified 2016 by Steve Manuel, Boss Sauce Creative, LLC
// All modifications are relicensed under the same BSD license
// found in the LICENSE file.

// Generate a self-signed X.509 certificate for a TLS server. Outputs to
// 'devcerts/cert.pem' and 'devcerts/key.pem' and will overwrite existing files.

package tls

import (
	"crypto/ecdsa"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"fmt"
	"log"
	"math/big"
	"net"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/ponzu-cms/ponzu/system/db"
)

func publicKey(priv interface{}) interface{} {
	switch k := priv.(type) {
	case *rsa.PrivateKey:
		return &k.PublicKey
	case *ecdsa.PrivateKey:
		return &k.PublicKey
	default:
		return nil
	}
}

func pemBlockForKey(priv interface{}) *pem.Block {
	switch k := priv.(type) {
	case *rsa.PrivateKey:
		return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
	case *ecdsa.PrivateKey:
		b, err := x509.MarshalECPrivateKey(k)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Unable to marshal ECDSA private key: %v", err)
			os.Exit(2)
		}
		return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
	default:
		return nil
	}
}

func setupDev() {
	var priv interface{}
	var err error

	priv, err = rsa.GenerateKey(rand.Reader, 2048)

	if err != nil {
		log.Fatalf("failed to generate private key: %s", err)
	}

	notBefore := time.Now()
	notAfter := notBefore.Add(time.Hour * 24 * 30) // valid for 30 days

	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
		log.Fatalf("failed to generate serial number: %s", err)
	}

	template := x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			Organization: []string{"Acme Co"},
		},
		NotBefore: notBefore,
		NotAfter:  notAfter,

		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		BasicConstraintsValid: true,
	}

	host := db.ConfigCache("domain")
	if host == "" {
		host = "localhost, 0.0.0.0"
	}
	hosts := strings.Split(host, ",")
	for _, h := range hosts {
		if ip := net.ParseIP(h); ip != nil {
			template.IPAddresses = append(template.IPAddresses, ip)
		} else {
			template.DNSNames = append(template.DNSNames, h)
		}
	}

	// make all certs CA
	template.IsCA = true
	template.KeyUsage |= x509.KeyUsageCertSign

	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
	if err != nil {
		log.Fatalln("Failed to create certificate:", err)
	}

	// overwrite/create directory for devcerts
	pwd, err := os.Getwd()
	if err != nil {
		log.Fatalln("Couldn't find working directory to locate or save dev certificates.")
	}

	devcertsPath := filepath.Join(pwd, "system", "tls", "devcerts")

	err = os.Mkdir(devcertsPath, os.ModePerm|os.ModePerm)
	if err != nil {
		log.Fatalln("Failed to create directory to locate or save dev certificates.")
	}

	certOut, err := os.Create(filepath.Join(devcertsPath, "cert.pem"))
	if err != nil {
		log.Fatalf("failed to open devcerts/cert.pem for writing: %s", err)
	}
	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
	certOut.Close()
	log.Print("written devcerts/cert.pem\n")

	keyOut, err := os.OpenFile(filepath.Join(devcertsPath, "key.pem"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		log.Print("failed to open devcerts/key.pem for writing:", err)
		return
	}
	pem.Encode(keyOut, pemBlockForKey(priv))
	keyOut.Close()
	log.Print("written devcerts/key.pem\n")
}
<commit_msg>adding error logging to debug<commit_after>// 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.

// Modified 2016 by Steve Manuel, Boss Sauce Creative, LLC
// All modifications are relicensed under the same BSD license
// found in the LICENSE file.

// Generate a self-signed X.509 certificate for a TLS server. Outputs to
// 'devcerts/cert.pem' and 'devcerts/key.pem' and will overwrite existing files.

package tls

import (
	"crypto/ecdsa"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"fmt"
	"log"
	"math/big"
	"net"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/ponzu-cms/ponzu/system/db"
)

func publicKey(priv interface{}) interface{} {
	switch k := priv.(type) {
	case *rsa.PrivateKey:
		return &k.PublicKey
	case *ecdsa.PrivateKey:
		return &k.PublicKey
	default:
		return nil
	}
}

func pemBlockForKey(priv interface{}) *pem.Block {
	switch k := priv.(type) {
	case *rsa.PrivateKey:
		return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
	case *ecdsa.PrivateKey:
		b, err := x509.MarshalECPrivateKey(k)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Unable to marshal ECDSA private key: %v", err)
			os.Exit(2)
		}
		return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
	default:
		return nil
	}
}

func setupDev() {
	var priv interface{}
	var err error

	priv, err = rsa.GenerateKey(rand.Reader, 2048)

	if err != nil {
		log.Fatalf("failed to generate private key: %s", err)
	}

	notBefore := time.Now()
	notAfter := notBefore.Add(time.Hour * 24 * 30) // valid for 30 days

	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
		log.Fatalf("failed to generate serial number: %s", err)
	}

	template := x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			Organization: []string{"Acme Co"},
		},
		NotBefore: notBefore,
		NotAfter:  notAfter,

		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		BasicConstraintsValid: true,
	}

	host := db.ConfigCache("domain")
	if host == "" {
		host = "localhost, 0.0.0.0"
	}
	hosts := strings.Split(host, ",")
	for _, h := range hosts {
		if ip := net.ParseIP(h); ip != nil {
			template.IPAddresses = append(template.IPAddresses, ip)
		} else {
			template.DNSNames = append(template.DNSNames, h)
		}
	}

	// make all certs CA
	template.IsCA = true
	template.KeyUsage |= x509.KeyUsageCertSign

	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
	if err != nil {
		log.Fatalln("Failed to create certificate:", err)
	}

	// overwrite/create directory for devcerts
	pwd, err := os.Getwd()
	if err != nil {
		log.Fatalln("Couldn't find working directory to locate or save dev certificates:", err)
	}

	devcertsPath := filepath.Join(pwd, "system", "tls", "devcerts")
	fmt.Println(devcertsPath)

	err = os.Mkdir(devcertsPath, os.ModePerm|os.ModePerm)
	if err != nil {
		log.Fatalln("Failed to create directory to locate or save dev certificates:", err)
	}

	certOut, err := os.Create(filepath.Join(devcertsPath, "cert.pem"))
	if err != nil {
		log.Fatalln("Failed to open devcerts/cert.pem for writing:", err)
	}
	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
	certOut.Close()

	keyOut, err := os.OpenFile(filepath.Join(devcertsPath, "key.pem"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		log.Fatalln("Failed to open devcerts/key.pem for writing:", err)
		return
	}
	pem.Encode(keyOut, pemBlockForKey(priv))
	keyOut.Close()
}
<|endoftext|>


<commit_before>package keyman

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

	"github.com/getlantern/byteexec"
	"github.com/getlantern/keyman/certimporter"
)

const (
	ROOT_CERT_STORE_NAME = "ROOT"
)

var (
	cebe *byteexec.Exec
)

func init() {
	exe, err := certimporter.Asset("certimporter.exe")
	if err != nil {
		panic(fmt.Errorf("Unable to get certimporter.exe: %s", err))
	}
	cebe, err = byteexec.New(exe, "certimporter")
	if err != nil {
		panic(fmt.Errorf("Unable to construct executable from memory: %s", err))
	}
}

func DeleteTrustedRootByName(commonName string, prompt string) error {
	cmd := elevatedIfNecessary(prompt)(cebe.Filename, "delete", ROOT_CERT_STORE_NAME, commonName)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("Unable to run certimporter.exe: %s\n%s", err, out)
	}
	return nil
}

func IsInstalled(cert *Certificate) (bool, error) {
	// TODO: make sure that passing byte strings of various encodings to the
	// certimporter program works in different languages/different usernames (
	// which end up in the temp path, etc.)
	cmd := cebe.Command("find", ROOT_CERT_STORE_NAME, cert.X509().Subject.CommonName)
	err := cmd.Run()

	// Consider the certificate found if and only if certimporter.exe exited
	// with a 0 exit code.  Any non-zero code (cert not found, or error looking
	// for cert) is treated as the cert not being found.
	found := err == nil
	return found, nil
}

// AddAsTrustedRootIfNeeded adds the certificate to the user's trust store as a trusted
// root CA.
func (cert *Certificate) AddAsTrustedRootIfNeeded(elevatePrompt, installPromptTitle, installPromptContent string) error {
	if IsInstalled(cert) {
		return nil
	}
	// Warn the user of what's about to happen
	if installPromptContent != "" && installPromptTitle != "" {
		cmd := exec.Command("mshta", fmt.Sprintf("javascript: var sh=new ActiveXObject('WScript.Shell'); sh.Popup('%v', 0, '%v', 64); close()", installPromptContent, installPromptTitle))
		promptErr := cmd.Run()
		if promptErr != nil {
			installErr = fmt.Errorf("Unable to show windows prompt for installing certificate: %v", promptErr)
			return installErr
		}
	}
	// Create a temp file containing the certificate
	tempFile, err := ioutil.TempFile("", "tempCert")
	defer os.Remove(tempFile.Name())
	if err != nil {
		return fmt.Errorf("Unable to create temp file: %s", err)
	}
	err = cert.WriteToDERFile(tempFile.Name())
	if err != nil {
		return fmt.Errorf("Unable to save certificate to temp file: %s", err)
	}

	// Add it as a trusted cert
	cmd := elevatedIfNecessary(elevatePrompt)(cebe.Filename, "add", ROOT_CERT_STORE_NAME, tempFile.Name())
	out, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("Unable to run certimporter.exe: %s\n%s", err, out)
	} else {
		return nil
	}
}
<commit_msg>win fix<commit_after>package keyman

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

	"github.com/getlantern/byteexec"
	"github.com/getlantern/keyman/certimporter"
)

const (
	ROOT_CERT_STORE_NAME = "ROOT"
)

var (
	cebe *byteexec.Exec
)

func init() {
	exe, err := certimporter.Asset("certimporter.exe")
	if err != nil {
		panic(fmt.Errorf("Unable to get certimporter.exe: %s", err))
	}
	cebe, err = byteexec.New(exe, "certimporter")
	if err != nil {
		panic(fmt.Errorf("Unable to construct executable from memory: %s", err))
	}
}

func DeleteTrustedRootByName(commonName string, prompt string) error {
	cmd := elevatedIfNecessary(prompt)(cebe.Filename, "delete", ROOT_CERT_STORE_NAME, commonName)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("Unable to run certimporter.exe: %s\n%s", err, out)
	}
	return nil
}

func IsInstalled(cert *Certificate) bool {
	// TODO: make sure that passing byte strings of various encodings to the
	// certimporter program works in different languages/different usernames (
	// which end up in the temp path, etc.)
	cmd := cebe.Command("find", ROOT_CERT_STORE_NAME, cert.X509().Subject.CommonName)
	err := cmd.Run()

	// Consider the certificate found if and only if certimporter.exe exited
	// with a 0 exit code.  Any non-zero code (cert not found, or error looking
	// for cert) is treated as the cert not being found.
	return err == nil
}

// AddAsTrustedRootIfNeeded adds the certificate to the user's trust store as a trusted
// root CA.
func (cert *Certificate) AddAsTrustedRootIfNeeded(elevatePrompt, installPromptTitle, installPromptContent string) error {
	if IsInstalled(cert) {
		return nil
	}
	// Warn the user of what's about to happen
	if installPromptContent != "" && installPromptTitle != "" {
		cmd := exec.Command("mshta", fmt.Sprintf("javascript: var sh=new ActiveXObject('WScript.Shell'); sh.Popup('%v', 0, '%v', 64); close()", installPromptContent, installPromptTitle))
		promptErr := cmd.Run()
		if promptErr != nil {
			installErr = fmt.Errorf("Unable to show windows prompt for installing certificate: %v", promptErr)
			return installErr
		}
	}
	// Create a temp file containing the certificate
	tempFile, err := ioutil.TempFile("", "tempCert")
	defer os.Remove(tempFile.Name())
	if err != nil {
		return fmt.Errorf("Unable to create temp file: %s", err)
	}
	err = cert.WriteToDERFile(tempFile.Name())
	if err != nil {
		return fmt.Errorf("Unable to save certificate to temp file: %s", err)
	}

	// Add it as a trusted cert
	cmd := elevatedIfNecessary(elevatePrompt)(cebe.Filename, "add", ROOT_CERT_STORE_NAME, tempFile.Name())
	out, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("Unable to run certimporter.exe: %s\n%s", err, out)
	} else {
		return nil
	}
}
<|endoftext|>


<commit_before>package postgres

var SchemaBase = []string{
	`CREATE TABLE IF NOT EXISTS channels (
        channel_id uuid PRIMARY KEY,
        client_id uuid,

        ext_id text NOT NULL,

        owners uuid[],

        root_thread_id uuid,

        created_at timestamp with time zone NOT NULL,
        updated_at timestamp with time zone DEFAULT now() NOT NULL,

        CONSTRAINT uniq_client_channels_idx UNIQUE (client_id, ext_id)
    )`,
	`CREATE TABLE IF NOT EXISTS threads (
        thread_id uuid PRIMARY KEY,
        client_id uuid,
        channel_id uuid,

        ext_id text NOT NULL,

        owners uuid[],

        related_event_id uuid, -- в случае root = nil, в других случая отражает event с которым связан "вверх" поток
	    parent_thread_id uuid, -- в случае root = nil

        created_at timestamp with time zone NOT NULL,
        updated_at timestamp with time zone DEFAULT now() NOT NULL,

        CONSTRAINT uniq_client_threads_ids_idx UNIQUE (client_id, thread_id),
        CONSTRAINT uniq_client_channel_threads_ext_ids_idx UNIQUE (client_id, channel_id, ext_id)
    )`,
	`CREATE TABLE IF NOT EXISTS events (
        event_id uuid PRIMARY KEY,
        client_id uuid,
        thread_id uuid,
        channel_id uuid,

        creator uuid,

        data bytea,

        parent_thread_id uuid,
        parent_event_id uuid,
        branch_thread_id uuid,

        created_at timestamp with time zone NOT NULL,
        updated_at timestamp with time zone DEFAULT now() NOT NULL,

        CONSTRAINT uniq_client_event_idx UNIQUE (client_id, event_id)
    )`,
	`CREATE TABLE IF NOT EXISTS threadline (
        client_id uuid,
        channel_id uuid,
        thread_id uuid,

        event_id uuid PRIMARY KEY,

        created_at timestamp with time zone NOT NULL
    )`,
	`CREATE INDEX IF NOT EXISTS threadline_created_index ON threadline(
        client_id asc,
--        channel_id asc,
        thread_id asc,
        created_at DESC,
        event_id ASC
        )`,
	// `CREATE TABLE IF NOT EXISTS thread_watchers (
	//     client_id uuid,
	//     thread_id uuid,
	//     user_id uuid,

	//     unread int8,

	//     CONSTRAINT uniq_client_thread_watchers_idx UNIQUE (client_id, thread_id, user_id)
	// )`,
	// `CREATE TABLE IF NOT EXISTS thread_counters (
	//     client_id uuid,
	//     thread_id uuid,

	//     counter_events int8,

	//     CONSTRAINT uniq_client_thread_counter_idx UNIQUE (client_id, thread_id)
	// )`,
	// `CREATE TABLE IF NOT EXISTS channel_watchers (
	//     client_id uuid,
	//     channel_id uuid,
	//     user_id uuid,

	//     unread int8,

	//     CONSTRAINT uniq_client_channel_watchers_idx UNIQUE (client_id, channel_id, user_id)
	// )`,
	// `CREATE TABLE IF NOT EXISTS channel_counters (
	//     client_id uuid,
	//     channel_id uuid,

	//     counter_events int8,

	//     CONSTRAINT uniq_client_channel_counter_idx UNIQUE (client_id, channel_id)
	// )`,
}
<commit_msg>bug fix - unique thread names in the channel<commit_after>package postgres

var SchemaBase = []string{
	`CREATE TABLE IF NOT EXISTS channels (
        channel_id uuid PRIMARY KEY,
        client_id uuid,

        ext_id text NOT NULL,

        owners uuid[],

        root_thread_id uuid,

        created_at timestamp with time zone NOT NULL,
        updated_at timestamp with time zone DEFAULT now() NOT NULL,

        CONSTRAINT uniq_client_channels_idx UNIQUE (client_id, ext_id)
    )`,
	`CREATE INDEX IF NOT EXISTS uniq_client_channels_idx ON channels(client_id, ext_id) WHERE (ext_id IS NOT NULL)`,
	`CREATE TABLE IF NOT EXISTS threads (
        thread_id uuid PRIMARY KEY,
        client_id uuid,
        channel_id uuid,

        ext_id text NOT NULL,

        owners uuid[],

        related_event_id uuid, -- в случае root = nil, в других случая отражает event с которым связан "вверх" поток
	    parent_thread_id uuid, -- в случае root = nil

        created_at timestamp with time zone NOT NULL,
        updated_at timestamp with time zone DEFAULT now() NOT NULL,

        CONSTRAINT uniq_client_threads_ids_idx UNIQUE (client_id, thread_id)
    )`,
	`CREATE INDEX IF NOT EXISTS uniq_client_channel_threads_ext_ids_idx ON threads(client_id, channel_id, ext_id) WHERE (ext_id IS NOT NULL)`,
	`CREATE TABLE IF NOT EXISTS events (
        event_id uuid PRIMARY KEY,
        client_id uuid,
        thread_id uuid,
        channel_id uuid,

        creator uuid,

        data bytea,

        parent_thread_id uuid,
        parent_event_id uuid,
        branch_thread_id uuid,

        created_at timestamp with time zone NOT NULL,
        updated_at timestamp with time zone DEFAULT now() NOT NULL,

        CONSTRAINT uniq_client_event_idx UNIQUE (client_id, event_id)
    )`,
	`CREATE TABLE IF NOT EXISTS threadline (
        client_id uuid,
        channel_id uuid,
        thread_id uuid,

        event_id uuid PRIMARY KEY,

        created_at timestamp with time zone NOT NULL
    )`,
	`CREATE INDEX IF NOT EXISTS threadline_created_index ON threadline(
        client_id asc,
--        channel_id asc,
        thread_id asc,
        created_at DESC,
        event_id ASC
        )`,
	// `CREATE TABLE IF NOT EXISTS thread_watchers (
	//     client_id uuid,
	//     thread_id uuid,
	//     user_id uuid,

	//     unread int8,

	//     CONSTRAINT uniq_client_thread_watchers_idx UNIQUE (client_id, thread_id, user_id)
	// )`,
	// `CREATE TABLE IF NOT EXISTS thread_counters (
	//     client_id uuid,
	//     thread_id uuid,

	//     counter_events int8,

	//     CONSTRAINT uniq_client_thread_counter_idx UNIQUE (client_id, thread_id)
	// )`,
	// `CREATE TABLE IF NOT EXISTS channel_watchers (
	//     client_id uuid,
	//     channel_id uuid,
	//     user_id uuid,

	//     unread int8,

	//     CONSTRAINT uniq_client_channel_watchers_idx UNIQUE (client_id, channel_id, user_id)
	// )`,
	// `CREATE TABLE IF NOT EXISTS channel_counters (
	//     client_id uuid,
	//     channel_id uuid,

	//     counter_events int8,

	//     CONSTRAINT uniq_client_channel_counter_idx UNIQUE (client_id, channel_id)
	// )`,
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/sha1"
	"fmt"
	"time"
	"os"

	"github.com/pkg/errors"

	"github.com/havoc-io/mutagen/cmd"
	"github.com/havoc-io/mutagen/sync"
)

var usage = `snapshot_bench [-h|--help] <path>
`

func main() {
	// Parse arguments.
	flagSet := cmd.NewFlagSet("snapshot_bench", usage, []int{1})
	path := flagSet.ParseOrDie(os.Args[1:])[0]

	// Print information.
	fmt.Println("Analyzing", path)

	// Create a snapshot without any cache.
	start := time.Now()
	snapshot, cache, err := sync.Snapshot(path, sha1.New(), nil)
	if err != nil {
		cmd.Fatal(errors.Wrap(err, "unable to create snapshot"))
	}
	stop := time.Now()
	fmt.Println("Cold snapshot took", stop.Sub(start))

	// Create a snapshot with a cache.
	start = time.Now()
	snapshot, _, err = sync.Snapshot(path, sha1.New(), cache)
	if err != nil {
		cmd.Fatal(errors.Wrap(err, "unable to create snapshot"))
	}
	stop = time.Now()
	fmt.Println("Warm snapshot took", stop.Sub(start))

	// Serialize it.
	start = time.Now()
	serialized, err := snapshot.Marshal()
	if err != nil {
		cmd.Fatal(errors.Wrap(err, "unable to serialize snapshot"))
	}
	stop = time.Now()
	fmt.Println("Serialization took", stop.Sub(start))

	// Deserialize it.
	start = time.Now()
	deserialized := &sync.Entry{}
	if err = deserialized.Unmarshal(serialized); err != nil {
		cmd.Fatal(errors.Wrap(err, "unable to deserialize snapshot"))
	}
	stop = time.Now()
	fmt.Println("Deserialization took", stop.Sub(start))

	// Print other information.
	fmt.Println("Serialized size was", len(serialized), "bytes")
	fmt.Println(
		"Original/deserialized snapshots equivalent?",
		deserialized.Equal(snapshot),
	)
}
<commit_msg>Updated snapshot_bench to analyze cache parameters.<commit_after>package main

import (
	"crypto/sha1"
	"fmt"
	"time"
	"os"

	"github.com/pkg/errors"

	"github.com/havoc-io/mutagen/cmd"
	"github.com/havoc-io/mutagen/sync"
)

var usage = `snapshot_bench [-h|--help] <path>
`

func main() {
	// Parse arguments.
	flagSet := cmd.NewFlagSet("snapshot_bench", usage, []int{1})
	path := flagSet.ParseOrDie(os.Args[1:])[0]

	// Print information.
	fmt.Println("Analyzing", path)

	// Create a snapshot without any cache.
	start := time.Now()
	snapshot, cache, err := sync.Snapshot(path, sha1.New(), nil)
	if err != nil {
		cmd.Fatal(errors.Wrap(err, "unable to create snapshot"))
	}
	stop := time.Now()
	fmt.Println("Cold snapshot took", stop.Sub(start))

	// Create a snapshot with a cache.
	start = time.Now()
	snapshot, _, err = sync.Snapshot(path, sha1.New(), cache)
	if err != nil {
		cmd.Fatal(errors.Wrap(err, "unable to create snapshot"))
	}
	stop = time.Now()
	fmt.Println("Warm snapshot took", stop.Sub(start))

	// Serialize it.
	start = time.Now()
	serialized, err := snapshot.Marshal()
	if err != nil {
		cmd.Fatal(errors.Wrap(err, "unable to serialize snapshot"))
	}
	stop = time.Now()
	fmt.Println("Serialization took", stop.Sub(start))

	// Deserialize it.
	start = time.Now()
	deserialized := &sync.Entry{}
	if err = deserialized.Unmarshal(serialized); err != nil {
		cmd.Fatal(errors.Wrap(err, "unable to deserialize snapshot"))
	}
	stop = time.Now()
	fmt.Println("Deserialization took", stop.Sub(start))

	// Print other information.
	fmt.Println("Serialized size was", len(serialized), "bytes")
	fmt.Println(
		"Original/deserialized snapshots equivalent?",
		deserialized.Equal(snapshot),
	)

	// Serialize the cache.
	start = time.Now()
	serializedCache, err := cache.Marshal()
	if err != nil {
		cmd.Fatal(errors.Wrap(err, "unable to serialize cache"))
	}
	stop = time.Now()
	fmt.Println("Cache serialization took", stop.Sub(start))

	// Deserialize the cache.
	start = time.Now()
	deserializedCache := &sync.Cache{}
	if err = deserializedCache.Unmarshal(serializedCache); err != nil {
		cmd.Fatal(errors.Wrap(err, "unable to deserialize cache"))
	}
	stop = time.Now()
	fmt.Println("Cache deserialization took", stop.Sub(start))

	// Print other information.
	fmt.Println("Serialized cache size was", len(serializedCache), "bytes")
}
<|endoftext|>


<commit_before>//
package google

import (
	"fmt"
	"reflect"

	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
	computeBeta "google.golang.org/api/compute/v0.beta"
	"google.golang.org/api/googleapi"
)

func instanceSchedulingNodeAffinitiesElemSchema() *schema.Resource {
	return &schema.Resource{
		Schema: map[string]*schema.Schema{
			"key": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"operator": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validation.StringInSlice([]string{"IN", "NOT_IN"}, false),
			},
			"values": {
				Type:     schema.TypeSet,
				Required: true,
				ForceNew: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set:      schema.HashString,
			},
		},
	}
}

func expandAliasIpRanges(ranges []interface{}) []*computeBeta.AliasIpRange {
	ipRanges := make([]*computeBeta.AliasIpRange, 0, len(ranges))
	for _, raw := range ranges {
		data := raw.(map[string]interface{})
		ipRanges = append(ipRanges, &computeBeta.AliasIpRange{
			IpCidrRange:         data["ip_cidr_range"].(string),
			SubnetworkRangeName: data["subnetwork_range_name"].(string),
		})
	}
	return ipRanges
}

func flattenAliasIpRange(ranges []*computeBeta.AliasIpRange) []map[string]interface{} {
	rangesSchema := make([]map[string]interface{}, 0, len(ranges))
	for _, ipRange := range ranges {
		rangesSchema = append(rangesSchema, map[string]interface{}{
			"ip_cidr_range":         ipRange.IpCidrRange,
			"subnetwork_range_name": ipRange.SubnetworkRangeName,
		})
	}
	return rangesSchema
}

func expandScheduling(v interface{}) (*computeBeta.Scheduling, error) {
	if v == nil {
		// We can't set default values for lists.
		return &computeBeta.Scheduling{
			AutomaticRestart: googleapi.Bool(true),
		}, nil
	}

	ls := v.([]interface{})
	if len(ls) == 0 {
		// We can't set default values for lists
		return &computeBeta.Scheduling{
			AutomaticRestart: googleapi.Bool(true),
		}, nil
	}

	if len(ls) > 1 || ls[0] == nil {
		return nil, fmt.Errorf("expected exactly one scheduling block")
	}

	original := ls[0].(map[string]interface{})
	scheduling := &computeBeta.Scheduling{
		ForceSendFields: make([]string, 0, 4),
	}

	if v, ok := original["automatic_restart"]; ok {
		scheduling.AutomaticRestart = googleapi.Bool(v.(bool))
		scheduling.ForceSendFields = append(scheduling.ForceSendFields, "AutomaticRestart")
	}

	if v, ok := original["preemptible"]; ok {
		scheduling.Preemptible = v.(bool)
		scheduling.ForceSendFields = append(scheduling.ForceSendFields, "Preemptible")
	}

	if v, ok := original["on_host_maintenance"]; ok {
		scheduling.OnHostMaintenance = v.(string)
		scheduling.ForceSendFields = append(scheduling.ForceSendFields, "OnHostMaintenance")
	}

	if v, ok := original["node_affinities"]; ok && v != nil {
		naSet := v.(*schema.Set).List()
		scheduling.NodeAffinities = make([]*computeBeta.SchedulingNodeAffinity, len(ls))
		scheduling.ForceSendFields = append(scheduling.ForceSendFields, "NodeAffinities")
		for _, nodeAffRaw := range naSet {
			if nodeAffRaw == nil {
				continue
			}
			nodeAff := nodeAffRaw.(map[string]interface{})
			transformed := &computeBeta.SchedulingNodeAffinity{
				Key:      nodeAff["key"].(string),
				Operator: nodeAff["operator"].(string),
				Values:   convertStringArr(nodeAff["values"].(*schema.Set).List()),
			}
			scheduling.NodeAffinities = append(scheduling.NodeAffinities, transformed)
		}
	}

	return scheduling, nil
}

func flattenScheduling(resp *computeBeta.Scheduling) []map[string]interface{} {
	schedulingMap := map[string]interface{}{
		"on_host_maintenance": resp.OnHostMaintenance,
		"preemptible":         resp.Preemptible,
	}

	if resp.AutomaticRestart != nil {
		schedulingMap["automatic_restart"] = *resp.AutomaticRestart
	}

	nodeAffinities := schema.NewSet(schema.HashResource(instanceSchedulingNodeAffinitiesElemSchema()), nil)
	for _, na := range resp.NodeAffinities {
		nodeAffinities.Add(map[string]interface{}{
			"key":      na.Key,
			"operator": na.Operator,
			"values":   schema.NewSet(schema.HashString, convertStringArrToInterface(na.Values)),
		})
	}
	schedulingMap["node_affinities"] = nodeAffinities

	return []map[string]interface{}{schedulingMap}
}

func flattenAccessConfigs(accessConfigs []*computeBeta.AccessConfig) ([]map[string]interface{}, string) {
	flattened := make([]map[string]interface{}, len(accessConfigs))
	natIP := ""
	for i, ac := range accessConfigs {
		flattened[i] = map[string]interface{}{
			"nat_ip":       ac.NatIP,
			"network_tier": ac.NetworkTier,
		}
		if ac.SetPublicPtr {
			flattened[i]["public_ptr_domain_name"] = ac.PublicPtrDomainName
		}
		if natIP == "" {
			natIP = ac.NatIP
		}
	}
	return flattened, natIP
}

func flattenNetworkInterfaces(d *schema.ResourceData, config *Config, networkInterfaces []*computeBeta.NetworkInterface) ([]map[string]interface{}, string, string, string, error) {
	flattened := make([]map[string]interface{}, len(networkInterfaces))
	var region, internalIP, externalIP string

	for i, iface := range networkInterfaces {
		var ac []map[string]interface{}
		ac, externalIP = flattenAccessConfigs(iface.AccessConfigs)

		subnet, err := ParseSubnetworkFieldValue(iface.Subnetwork, d, config)
		if err != nil {
			return nil, "", "", "", err
		}
		region = subnet.Region

		flattened[i] = map[string]interface{}{
			"network_ip":         iface.NetworkIP,
			"network":            ConvertSelfLinkToV1(iface.Network),
			"subnetwork":         ConvertSelfLinkToV1(iface.Subnetwork),
			"subnetwork_project": subnet.Project,
			"access_config":      ac,
			"alias_ip_range":     flattenAliasIpRange(iface.AliasIpRanges),
			"nic_type":           iface.NicType,
		}
		// Instance template interfaces never have names, so they're absent
		// in the instance template network_interface schema. We want to use the
		// same flattening code for both resource types, so we avoid trying to
		// set the name field when it's not set at the GCE end.
		if iface.Name != "" {
			flattened[i]["name"] = iface.Name
		}
		if internalIP == "" {
			internalIP = iface.NetworkIP
		}
	}
	return flattened, region, internalIP, externalIP, nil
}

func expandAccessConfigs(configs []interface{}) []*computeBeta.AccessConfig {
	acs := make([]*computeBeta.AccessConfig, len(configs))
	for i, raw := range configs {
		acs[i] = &computeBeta.AccessConfig{}
		acs[i].Type = "ONE_TO_ONE_NAT"
		if raw != nil {
			data := raw.(map[string]interface{})
			acs[i].NatIP = data["nat_ip"].(string)
			acs[i].NetworkTier = data["network_tier"].(string)
			if ptr, ok := data["public_ptr_domain_name"]; ok && ptr != "" {
				acs[i].SetPublicPtr = true
				acs[i].PublicPtrDomainName = ptr.(string)
			}
		}
	}
	return acs
}

func expandNetworkInterfaces(d TerraformResourceData, config *Config) ([]*computeBeta.NetworkInterface, error) {
	configs := d.Get("network_interface").([]interface{})
	ifaces := make([]*computeBeta.NetworkInterface, len(configs))
	for i, raw := range configs {
		data := raw.(map[string]interface{})

		network := data["network"].(string)
		subnetwork := data["subnetwork"].(string)
		if network == "" && subnetwork == "" {
			return nil, fmt.Errorf("exactly one of network or subnetwork must be provided")
		}

		nf, err := ParseNetworkFieldValue(network, d, config)
		if err != nil {
			return nil, fmt.Errorf("cannot determine self_link for network %q: %s", network, err)
		}

		subnetProjectField := fmt.Sprintf("network_interface.%d.subnetwork_project", i)
		sf, err := ParseSubnetworkFieldValueWithProjectField(subnetwork, subnetProjectField, d, config)
		if err != nil {
			return nil, fmt.Errorf("cannot determine self_link for subnetwork %q: %s", subnetwork, err)
		}

		ifaces[i] = &computeBeta.NetworkInterface{
			NetworkIP:     data["network_ip"].(string),
			Network:       nf.RelativeLink(),
			Subnetwork:    sf.RelativeLink(),
			AccessConfigs: expandAccessConfigs(data["access_config"].([]interface{})),
			AliasIpRanges: expandAliasIpRanges(data["alias_ip_range"].([]interface{})),
			NicType:       expandNicType(data["nic_type"].(interface{})),
		}
	}
	return ifaces, nil
}

func expandNicType(d interface{}) string {
	if d == nil {
		return ""
	}
	return d.(string)
}

func flattenServiceAccounts(serviceAccounts []*computeBeta.ServiceAccount) []map[string]interface{} {
	result := make([]map[string]interface{}, len(serviceAccounts))
	for i, serviceAccount := range serviceAccounts {
		result[i] = map[string]interface{}{
			"email":  serviceAccount.Email,
			"scopes": schema.NewSet(stringScopeHashcode, convertStringArrToInterface(serviceAccount.Scopes)),
		}
	}
	return result
}

func expandServiceAccounts(configs []interface{}) []*computeBeta.ServiceAccount {
	accounts := make([]*computeBeta.ServiceAccount, len(configs))
	for i, raw := range configs {
		data := raw.(map[string]interface{})

		accounts[i] = &computeBeta.ServiceAccount{
			Email:  data["email"].(string),
			Scopes: canonicalizeServiceScopes(convertStringSet(data["scopes"].(*schema.Set))),
		}

		if accounts[i].Email == "" {
			accounts[i].Email = "default"
		}
	}
	return accounts
}

func flattenGuestAccelerators(accelerators []*computeBeta.AcceleratorConfig) []map[string]interface{} {
	acceleratorsSchema := make([]map[string]interface{}, len(accelerators))
	for i, accelerator := range accelerators {
		acceleratorsSchema[i] = map[string]interface{}{
			"count": accelerator.AcceleratorCount,
			"type":  accelerator.AcceleratorType,
		}
	}
	return acceleratorsSchema
}

func resourceInstanceTags(d TerraformResourceData) *computeBeta.Tags {
	// Calculate the tags
	var tags *computeBeta.Tags
	if v := d.Get("tags"); v != nil {
		vs := v.(*schema.Set)
		tags = new(computeBeta.Tags)
		tags.Items = make([]string, vs.Len())
		for i, v := range vs.List() {
			tags.Items[i] = v.(string)
		}

		tags.Fingerprint = d.Get("tags_fingerprint").(string)
	}

	return tags
}

func expandShieldedVmConfigs(d TerraformResourceData) *computeBeta.ShieldedInstanceConfig {
	if _, ok := d.GetOk("shielded_instance_config"); !ok {
		return nil
	}

	prefix := "shielded_instance_config.0"
	return &computeBeta.ShieldedInstanceConfig{
		EnableSecureBoot:          d.Get(prefix + ".enable_secure_boot").(bool),
		EnableVtpm:                d.Get(prefix + ".enable_vtpm").(bool),
		EnableIntegrityMonitoring: d.Get(prefix + ".enable_integrity_monitoring").(bool),
		ForceSendFields:           []string{"EnableSecureBoot", "EnableVtpm", "EnableIntegrityMonitoring"},
	}
}

func expandConfidentialInstanceConfig(d TerraformResourceData) *computeBeta.ConfidentialInstanceConfig {
	if _, ok := d.GetOk("confidential_instance_config"); !ok {
		return nil
	}

	prefix := "confidential_instance_config.0"
	return &computeBeta.ConfidentialInstanceConfig{
		EnableConfidentialCompute: d.Get(prefix + ".enable_confidential_compute").(bool),
		ForceSendFields:           []string{"EnableSecureBoot"},
	}
}

func flattenConfidentialInstanceConfig(ConfidentialInstanceConfig *computeBeta.ConfidentialInstanceConfig) []map[string]bool {
	if ConfidentialInstanceConfig == nil {
		return nil
	}

	return []map[string]bool{{
		"enable_confidential_compute": ConfidentialInstanceConfig.EnableConfidentialCompute,
	}}
}

func flattenShieldedVmConfig(shieldedVmConfig *computeBeta.ShieldedInstanceConfig) []map[string]bool {
	if shieldedVmConfig == nil {
		return nil
	}

	return []map[string]bool{{
		"enable_secure_boot":          shieldedVmConfig.EnableSecureBoot,
		"enable_vtpm":                 shieldedVmConfig.EnableVtpm,
		"enable_integrity_monitoring": shieldedVmConfig.EnableIntegrityMonitoring,
	}}
}

func expandDisplayDevice(d TerraformResourceData) *computeBeta.DisplayDevice {
	if _, ok := d.GetOk("enable_display"); !ok {
		return nil
	}
	return &computeBeta.DisplayDevice{
		EnableDisplay:   d.Get("enable_display").(bool),
		ForceSendFields: []string{"EnableDisplay"},
	}
}

func flattenEnableDisplay(displayDevice *computeBeta.DisplayDevice) interface{} {
	if displayDevice == nil {
		return nil
	}

	return displayDevice.EnableDisplay
}

// Terraform doesn't correctly calculate changes on schema.Set, so we do it manually
// https://github.com/hashicorp/terraform-plugin-sdk/issues/98
func schedulingHasChange(d *schema.ResourceData) bool {
	if !d.HasChange("scheduling") {
		// This doesn't work correctly, which is why this method exists
		// But it is here for posterity
		return false
	}
	o, n := d.GetChange("scheduling")
	oScheduling := o.([]interface{})[0].(map[string]interface{})
	newScheduling := n.([]interface{})[0].(map[string]interface{})
	originalNa := oScheduling["node_affinities"].(*schema.Set)
	newNa := newScheduling["node_affinities"].(*schema.Set)
	if oScheduling["automatic_restart"] != newScheduling["automatic_restart"] {
		return true
	}

	if oScheduling["preemptible"] != newScheduling["preemptible"] {
		return true
	}

	if oScheduling["on_host_maintenance"] != newScheduling["on_host_maintenance"] {
		return true
	}

	return reflect.DeepEqual(newNa, originalNa)
}
<commit_msg>Made nic_type expansion expect a string (#4598) (#656)<commit_after>//
package google

import (
	"fmt"
	"reflect"

	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
	computeBeta "google.golang.org/api/compute/v0.beta"
	"google.golang.org/api/googleapi"
)

func instanceSchedulingNodeAffinitiesElemSchema() *schema.Resource {
	return &schema.Resource{
		Schema: map[string]*schema.Schema{
			"key": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"operator": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validation.StringInSlice([]string{"IN", "NOT_IN"}, false),
			},
			"values": {
				Type:     schema.TypeSet,
				Required: true,
				ForceNew: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set:      schema.HashString,
			},
		},
	}
}

func expandAliasIpRanges(ranges []interface{}) []*computeBeta.AliasIpRange {
	ipRanges := make([]*computeBeta.AliasIpRange, 0, len(ranges))
	for _, raw := range ranges {
		data := raw.(map[string]interface{})
		ipRanges = append(ipRanges, &computeBeta.AliasIpRange{
			IpCidrRange:         data["ip_cidr_range"].(string),
			SubnetworkRangeName: data["subnetwork_range_name"].(string),
		})
	}
	return ipRanges
}

func flattenAliasIpRange(ranges []*computeBeta.AliasIpRange) []map[string]interface{} {
	rangesSchema := make([]map[string]interface{}, 0, len(ranges))
	for _, ipRange := range ranges {
		rangesSchema = append(rangesSchema, map[string]interface{}{
			"ip_cidr_range":         ipRange.IpCidrRange,
			"subnetwork_range_name": ipRange.SubnetworkRangeName,
		})
	}
	return rangesSchema
}

func expandScheduling(v interface{}) (*computeBeta.Scheduling, error) {
	if v == nil {
		// We can't set default values for lists.
		return &computeBeta.Scheduling{
			AutomaticRestart: googleapi.Bool(true),
		}, nil
	}

	ls := v.([]interface{})
	if len(ls) == 0 {
		// We can't set default values for lists
		return &computeBeta.Scheduling{
			AutomaticRestart: googleapi.Bool(true),
		}, nil
	}

	if len(ls) > 1 || ls[0] == nil {
		return nil, fmt.Errorf("expected exactly one scheduling block")
	}

	original := ls[0].(map[string]interface{})
	scheduling := &computeBeta.Scheduling{
		ForceSendFields: make([]string, 0, 4),
	}

	if v, ok := original["automatic_restart"]; ok {
		scheduling.AutomaticRestart = googleapi.Bool(v.(bool))
		scheduling.ForceSendFields = append(scheduling.ForceSendFields, "AutomaticRestart")
	}

	if v, ok := original["preemptible"]; ok {
		scheduling.Preemptible = v.(bool)
		scheduling.ForceSendFields = append(scheduling.ForceSendFields, "Preemptible")
	}

	if v, ok := original["on_host_maintenance"]; ok {
		scheduling.OnHostMaintenance = v.(string)
		scheduling.ForceSendFields = append(scheduling.ForceSendFields, "OnHostMaintenance")
	}

	if v, ok := original["node_affinities"]; ok && v != nil {
		naSet := v.(*schema.Set).List()
		scheduling.NodeAffinities = make([]*computeBeta.SchedulingNodeAffinity, len(ls))
		scheduling.ForceSendFields = append(scheduling.ForceSendFields, "NodeAffinities")
		for _, nodeAffRaw := range naSet {
			if nodeAffRaw == nil {
				continue
			}
			nodeAff := nodeAffRaw.(map[string]interface{})
			transformed := &computeBeta.SchedulingNodeAffinity{
				Key:      nodeAff["key"].(string),
				Operator: nodeAff["operator"].(string),
				Values:   convertStringArr(nodeAff["values"].(*schema.Set).List()),
			}
			scheduling.NodeAffinities = append(scheduling.NodeAffinities, transformed)
		}
	}

	return scheduling, nil
}

func flattenScheduling(resp *computeBeta.Scheduling) []map[string]interface{} {
	schedulingMap := map[string]interface{}{
		"on_host_maintenance": resp.OnHostMaintenance,
		"preemptible":         resp.Preemptible,
	}

	if resp.AutomaticRestart != nil {
		schedulingMap["automatic_restart"] = *resp.AutomaticRestart
	}

	nodeAffinities := schema.NewSet(schema.HashResource(instanceSchedulingNodeAffinitiesElemSchema()), nil)
	for _, na := range resp.NodeAffinities {
		nodeAffinities.Add(map[string]interface{}{
			"key":      na.Key,
			"operator": na.Operator,
			"values":   schema.NewSet(schema.HashString, convertStringArrToInterface(na.Values)),
		})
	}
	schedulingMap["node_affinities"] = nodeAffinities

	return []map[string]interface{}{schedulingMap}
}

func flattenAccessConfigs(accessConfigs []*computeBeta.AccessConfig) ([]map[string]interface{}, string) {
	flattened := make([]map[string]interface{}, len(accessConfigs))
	natIP := ""
	for i, ac := range accessConfigs {
		flattened[i] = map[string]interface{}{
			"nat_ip":       ac.NatIP,
			"network_tier": ac.NetworkTier,
		}
		if ac.SetPublicPtr {
			flattened[i]["public_ptr_domain_name"] = ac.PublicPtrDomainName
		}
		if natIP == "" {
			natIP = ac.NatIP
		}
	}
	return flattened, natIP
}

func flattenNetworkInterfaces(d *schema.ResourceData, config *Config, networkInterfaces []*computeBeta.NetworkInterface) ([]map[string]interface{}, string, string, string, error) {
	flattened := make([]map[string]interface{}, len(networkInterfaces))
	var region, internalIP, externalIP string

	for i, iface := range networkInterfaces {
		var ac []map[string]interface{}
		ac, externalIP = flattenAccessConfigs(iface.AccessConfigs)

		subnet, err := ParseSubnetworkFieldValue(iface.Subnetwork, d, config)
		if err != nil {
			return nil, "", "", "", err
		}
		region = subnet.Region

		flattened[i] = map[string]interface{}{
			"network_ip":         iface.NetworkIP,
			"network":            ConvertSelfLinkToV1(iface.Network),
			"subnetwork":         ConvertSelfLinkToV1(iface.Subnetwork),
			"subnetwork_project": subnet.Project,
			"access_config":      ac,
			"alias_ip_range":     flattenAliasIpRange(iface.AliasIpRanges),
			"nic_type":           iface.NicType,
		}
		// Instance template interfaces never have names, so they're absent
		// in the instance template network_interface schema. We want to use the
		// same flattening code for both resource types, so we avoid trying to
		// set the name field when it's not set at the GCE end.
		if iface.Name != "" {
			flattened[i]["name"] = iface.Name
		}
		if internalIP == "" {
			internalIP = iface.NetworkIP
		}
	}
	return flattened, region, internalIP, externalIP, nil
}

func expandAccessConfigs(configs []interface{}) []*computeBeta.AccessConfig {
	acs := make([]*computeBeta.AccessConfig, len(configs))
	for i, raw := range configs {
		acs[i] = &computeBeta.AccessConfig{}
		acs[i].Type = "ONE_TO_ONE_NAT"
		if raw != nil {
			data := raw.(map[string]interface{})
			acs[i].NatIP = data["nat_ip"].(string)
			acs[i].NetworkTier = data["network_tier"].(string)
			if ptr, ok := data["public_ptr_domain_name"]; ok && ptr != "" {
				acs[i].SetPublicPtr = true
				acs[i].PublicPtrDomainName = ptr.(string)
			}
		}
	}
	return acs
}

func expandNetworkInterfaces(d TerraformResourceData, config *Config) ([]*computeBeta.NetworkInterface, error) {
	configs := d.Get("network_interface").([]interface{})
	ifaces := make([]*computeBeta.NetworkInterface, len(configs))
	for i, raw := range configs {
		data := raw.(map[string]interface{})

		network := data["network"].(string)
		subnetwork := data["subnetwork"].(string)
		if network == "" && subnetwork == "" {
			return nil, fmt.Errorf("exactly one of network or subnetwork must be provided")
		}

		nf, err := ParseNetworkFieldValue(network, d, config)
		if err != nil {
			return nil, fmt.Errorf("cannot determine self_link for network %q: %s", network, err)
		}

		subnetProjectField := fmt.Sprintf("network_interface.%d.subnetwork_project", i)
		sf, err := ParseSubnetworkFieldValueWithProjectField(subnetwork, subnetProjectField, d, config)
		if err != nil {
			return nil, fmt.Errorf("cannot determine self_link for subnetwork %q: %s", subnetwork, err)
		}

		ifaces[i] = &computeBeta.NetworkInterface{
			NetworkIP:     data["network_ip"].(string),
			Network:       nf.RelativeLink(),
			Subnetwork:    sf.RelativeLink(),
			AccessConfigs: expandAccessConfigs(data["access_config"].([]interface{})),
			AliasIpRanges: expandAliasIpRanges(data["alias_ip_range"].([]interface{})),
			NicType:       data["nic_type"].(string),
		}
	}
	return ifaces, nil
}

func flattenServiceAccounts(serviceAccounts []*computeBeta.ServiceAccount) []map[string]interface{} {
	result := make([]map[string]interface{}, len(serviceAccounts))
	for i, serviceAccount := range serviceAccounts {
		result[i] = map[string]interface{}{
			"email":  serviceAccount.Email,
			"scopes": schema.NewSet(stringScopeHashcode, convertStringArrToInterface(serviceAccount.Scopes)),
		}
	}
	return result
}

func expandServiceAccounts(configs []interface{}) []*computeBeta.ServiceAccount {
	accounts := make([]*computeBeta.ServiceAccount, len(configs))
	for i, raw := range configs {
		data := raw.(map[string]interface{})

		accounts[i] = &computeBeta.ServiceAccount{
			Email:  data["email"].(string),
			Scopes: canonicalizeServiceScopes(convertStringSet(data["scopes"].(*schema.Set))),
		}

		if accounts[i].Email == "" {
			accounts[i].Email = "default"
		}
	}
	return accounts
}

func flattenGuestAccelerators(accelerators []*computeBeta.AcceleratorConfig) []map[string]interface{} {
	acceleratorsSchema := make([]map[string]interface{}, len(accelerators))
	for i, accelerator := range accelerators {
		acceleratorsSchema[i] = map[string]interface{}{
			"count": accelerator.AcceleratorCount,
			"type":  accelerator.AcceleratorType,
		}
	}
	return acceleratorsSchema
}

func resourceInstanceTags(d TerraformResourceData) *computeBeta.Tags {
	// Calculate the tags
	var tags *computeBeta.Tags
	if v := d.Get("tags"); v != nil {
		vs := v.(*schema.Set)
		tags = new(computeBeta.Tags)
		tags.Items = make([]string, vs.Len())
		for i, v := range vs.List() {
			tags.Items[i] = v.(string)
		}

		tags.Fingerprint = d.Get("tags_fingerprint").(string)
	}

	return tags
}

func expandShieldedVmConfigs(d TerraformResourceData) *computeBeta.ShieldedInstanceConfig {
	if _, ok := d.GetOk("shielded_instance_config"); !ok {
		return nil
	}

	prefix := "shielded_instance_config.0"
	return &computeBeta.ShieldedInstanceConfig{
		EnableSecureBoot:          d.Get(prefix + ".enable_secure_boot").(bool),
		EnableVtpm:                d.Get(prefix + ".enable_vtpm").(bool),
		EnableIntegrityMonitoring: d.Get(prefix + ".enable_integrity_monitoring").(bool),
		ForceSendFields:           []string{"EnableSecureBoot", "EnableVtpm", "EnableIntegrityMonitoring"},
	}
}

func expandConfidentialInstanceConfig(d TerraformResourceData) *computeBeta.ConfidentialInstanceConfig {
	if _, ok := d.GetOk("confidential_instance_config"); !ok {
		return nil
	}

	prefix := "confidential_instance_config.0"
	return &computeBeta.ConfidentialInstanceConfig{
		EnableConfidentialCompute: d.Get(prefix + ".enable_confidential_compute").(bool),
		ForceSendFields:           []string{"EnableSecureBoot"},
	}
}

func flattenConfidentialInstanceConfig(ConfidentialInstanceConfig *computeBeta.ConfidentialInstanceConfig) []map[string]bool {
	if ConfidentialInstanceConfig == nil {
		return nil
	}

	return []map[string]bool{{
		"enable_confidential_compute": ConfidentialInstanceConfig.EnableConfidentialCompute,
	}}
}

func flattenShieldedVmConfig(shieldedVmConfig *computeBeta.ShieldedInstanceConfig) []map[string]bool {
	if shieldedVmConfig == nil {
		return nil
	}

	return []map[string]bool{{
		"enable_secure_boot":          shieldedVmConfig.EnableSecureBoot,
		"enable_vtpm":                 shieldedVmConfig.EnableVtpm,
		"enable_integrity_monitoring": shieldedVmConfig.EnableIntegrityMonitoring,
	}}
}

func expandDisplayDevice(d TerraformResourceData) *computeBeta.DisplayDevice {
	if _, ok := d.GetOk("enable_display"); !ok {
		return nil
	}
	return &computeBeta.DisplayDevice{
		EnableDisplay:   d.Get("enable_display").(bool),
		ForceSendFields: []string{"EnableDisplay"},
	}
}

func flattenEnableDisplay(displayDevice *computeBeta.DisplayDevice) interface{} {
	if displayDevice == nil {
		return nil
	}

	return displayDevice.EnableDisplay
}

// Terraform doesn't correctly calculate changes on schema.Set, so we do it manually
// https://github.com/hashicorp/terraform-plugin-sdk/issues/98
func schedulingHasChange(d *schema.ResourceData) bool {
	if !d.HasChange("scheduling") {
		// This doesn't work correctly, which is why this method exists
		// But it is here for posterity
		return false
	}
	o, n := d.GetChange("scheduling")
	oScheduling := o.([]interface{})[0].(map[string]interface{})
	newScheduling := n.([]interface{})[0].(map[string]interface{})
	originalNa := oScheduling["node_affinities"].(*schema.Set)
	newNa := newScheduling["node_affinities"].(*schema.Set)
	if oScheduling["automatic_restart"] != newScheduling["automatic_restart"] {
		return true
	}

	if oScheduling["preemptible"] != newScheduling["preemptible"] {
		return true
	}

	if oScheduling["on_host_maintenance"] != newScheduling["on_host_maintenance"] {
		return true
	}

	return reflect.DeepEqual(newNa, originalNa)
}
<|endoftext|>


<commit_before>//TODO: explain how to delete the image.
package bsu

import (
	"crypto/tls"
	"net/http"
	"testing"

	"github.com/hashicorp/packer/builder/osc/common"
	builderT "github.com/hashicorp/packer/helper/builder/testing"
	"github.com/outscale/osc-go/oapi"
)

func TestBuilderAcc_basic(t *testing.T) {
	builderT.Test(t, builderT.TestCase{
		PreCheck:             func() { testAccPreCheck(t) },
		Builder:              &Builder{},
		Template:             testBuilderAccBasic,
		SkipArtifactTeardown: true,
	})
}

func testAccPreCheck(t *testing.T) {
}

func testOAPIConn() (*oapi.Client, error) {
	access := &common.AccessConfig{RawRegion: "us-east-1"}
	clientConfig, err := access.Config()
	if err != nil {
		return nil, err
	}

	skipClient := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		},
	}

	return oapi.NewClient(clientConfig, skipClient), nil
}

const testBuilderAccBasic = `
{
	"builders": [{
		"type": "test",
		"region": "eu-west-2",
		"vm_type": "t2.micro",
		"source_omi": "ami-abe953fa",
		"ssh_username": "outscale",
		"omi_name": "packer-test {{timestamp}}",
		"associate_public_ip_address": true
	}]
}
`
<commit_msg>chore: added forece_deregister in the test case to verify the step_deregister_omi<commit_after>//TODO: explain how to delete the image.
package bsu

import (
	"crypto/tls"
	"net/http"
	"testing"

	"github.com/hashicorp/packer/builder/osc/common"
	builderT "github.com/hashicorp/packer/helper/builder/testing"
	"github.com/outscale/osc-go/oapi"
)

func TestBuilderAcc_basic(t *testing.T) {
	builderT.Test(t, builderT.TestCase{
		PreCheck:             func() { testAccPreCheck(t) },
		Builder:              &Builder{},
		Template:             testBuilderAccBasic,
		SkipArtifactTeardown: true,
	})
}

func testAccPreCheck(t *testing.T) {
}

func testOAPIConn() (*oapi.Client, error) {
	access := &common.AccessConfig{RawRegion: "us-east-1"}
	clientConfig, err := access.Config()
	if err != nil {
		return nil, err
	}

	skipClient := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		},
	}

	return oapi.NewClient(clientConfig, skipClient), nil
}

const testBuilderAccBasic = `
{
	"builders": [{
		"type": "test",
		"region": "eu-west-2",
		"vm_type": "t2.micro",
		"source_omi": "ami-abe953fa",
		"ssh_username": "outscale",
		"omi_name": "packer-test {{timestamp}}",
		"associate_public_ip_address": true,
		"force_deregister": true
	}]
}
`
<|endoftext|>