<commit_before>package gui

import (
	"strings"
	"unicode/utf8"

	"github.com/felixangell/nate/cfg"
	"github.com/felixangell/nate/gfx"
	"github.com/veandco/go-sdl2/sdl"
	"github.com/veandco/go-sdl2/sdl_ttf"
	"github.com/vinzmay/go-rope"
)

var (
	timer        uint32 = 0
	reset_timer  uint32 = 0
	should_draw  bool   = true
	should_flash bool
)

type Buffer struct {
	BaseComponent
	font     *ttf.Font
	contents []*rope.Rope
	curs     *Cursor
	cfg      *cfg.TomlConfig
}

func NewBuffer(conf *cfg.TomlConfig) *Buffer {
	font, err := ttf.OpenFont("./res/firacode.ttf", 24)
	if err != nil {
		panic(err)
	}

	config := conf
	if config == nil {
		config = cfg.NewDefaultConfig()
	}

	buff := &Buffer{
		contents: []*rope.Rope{},
		font:     font,
		curs:     &Cursor{},
		cfg:      config,
	}
	buff.appendLine("This is a test 世界.")
	return buff
}

func (b *Buffer) Dispose() {
	for _, texture := range TEXTURE_CACHE {
		texture.Destroy()
	}
}

func (b *Buffer) Init() {}

func (b *Buffer) appendLine(val string) {
	b.contents = append(b.contents, rope.New(val))
	b.curs.move(len(val), 0)
}

func (b *Buffer) processTextInput(t *sdl.TextInputEvent) {
	// TODO: how the fuck do decode this properly?
	rawVal, size := utf8.DecodeLastRune(t.Text[:1])
	if rawVal == utf8.RuneError || size == 0 {
		return
	}

	b.contents[b.curs.y] = b.contents[b.curs.y].Insert(b.curs.x, string(rawVal))
	b.curs.move(1, 0)
}

func (b *Buffer) processActionKey(t *sdl.KeyDownEvent) {
	switch t.Keysym.Scancode {
	case sdl.SCANCODE_RETURN:
		initial_x := b.curs.x
		prevLineLen := b.contents[b.curs.y].Len()

		var newRope *rope.Rope
		if initial_x < prevLineLen && initial_x > 0 {
			left, right := b.contents[b.curs.y].Split(initial_x)
			newRope = right
			b.contents[b.curs.y] = left
		} else if initial_x == 0 {
			b.contents = append(b.contents, new(rope.Rope))      // grow
			copy(b.contents[b.curs.y+1:], b.contents[b.curs.y:]) // shift
			b.contents[b.curs.y] = new(rope.Rope)                // set
			b.curs.move(0, 1)
			return
		} else {
			newRope = rope.New(" ")
		}

		b.curs.move(0, 1)
		for x := 0; x < initial_x; x++ {
			// TODO(Felix): there's a bug here where
			// this doesn't account for the rendered x
			// position when we use tabs as tabs and not spaces
			b.curs.move(-1, 0)
		}
		b.contents = append(b.contents, newRope)
	case sdl.SCANCODE_BACKSPACE:
		if b.curs.x > 0 {
			offs := -1
			if !b.cfg.Editor.Tabs_Are_Spaces {
				if b.contents[b.curs.y].Index(b.curs.x) == '\t' {
					offs = int(-b.cfg.Editor.Tab_Size)
				}
			} else if b.cfg.Editor.Hungry_Backspace && b.curs.x >= int(b.cfg.Editor.Tab_Size) {
				// FIXME wtf how does Substr even work
				// cut out the last {TAB_SIZE} amount of characters
				// and check em
				tabSize := int(b.cfg.Editor.Tab_Size)
				lastTabSizeChars := b.contents[b.curs.y].Substr(b.curs.x+1-tabSize, tabSize).String()
				artificialTab := string(make([]rune, tabSize, ' '))
				if strings.Compare(lastTabSizeChars, artificialTab) == 0 {
					// delete {TAB_SIZE} amount of characters
					// from the cursors x pos
					for i := 0; i < int(b.cfg.Editor.Tab_Size); i++ {
						b.contents[b.curs.y] = b.contents[b.curs.y].Delete(b.curs.x, 1)
						b.curs.move(-1, 0)
					}
					break
				}
			}

			b.contents[b.curs.y] = b.contents[b.curs.y].Delete(b.curs.x, 1)
			b.curs.moveRender(-1, 0, offs, 0)
		} else if b.curs.x == 0 && b.curs.y > 0 {
			// start of line, wrap to previous
			// two cases here:

			// the line_len is zero, in which case
			// we delete the line and go to the end
			// of the previous line
			if b.contents[b.curs.y].Len() == 0 {
				b.curs.move(b.contents[b.curs.y-1].Len(), -1)
				// FIXME, delete from the curs.y dont pop!
				b.contents = b.contents[:len(b.contents)-1]
				return
			}

			// TODO(Felix): handle all the edge cases here...

			// or, the line has characters, so we join
			// that line with the previous line
			prevLineLen := b.contents[b.curs.y-1].Len()
			b.contents[b.curs.y-1] = b.contents[b.curs.y-1].Concat(b.contents[b.curs.y])
			b.contents = append(b.contents[:b.curs.y], b.contents[b.curs.y+1:]...)
			b.curs.move(prevLineLen, -1)
		}
	case sdl.SCANCODE_RIGHT:
		currLineLength := b.contents[b.curs.y].Len()
		if b.curs.x >= currLineLength && b.curs.y < len(b.contents)-1 {
			// we're at the end of the line and we have
			// some lines after, let's wrap around
			b.curs.move(0, 1)
			b.curs.move(-currLineLength, 0)
		} else if b.curs.x < b.contents[b.curs.y].Len() {
			// we have characters to the right, let's move along
			b.curs.move(1, 0)
		}
	case sdl.SCANCODE_LEFT:
		if b.curs.x == 0 && b.curs.y > 0 {
			b.curs.move(b.contents[b.curs.y-1].Len(), -1)

		} else if b.curs.x > 0 {
			b.curs.move(-1, 0)
		}
	case sdl.SCANCODE_TAB:
		if b.cfg.Editor.Tabs_Are_Spaces {
			// make an empty rune array of TAB_SIZE, cast to string
			// and insert it.
			b.contents[b.curs.y] = b.contents[b.curs.y].Insert(b.curs.x, "    ")
			b.curs.move(int(b.cfg.Editor.Tab_Size), 0)
		} else {
			b.contents[b.curs.y] = b.contents[b.curs.y].Insert(b.curs.x, string('\t'))
			// the actual position is + 1, but we make it
			// move by TAB_SIZE characters on the view.
			b.curs.moveRender(1, 0, int(b.cfg.Editor.Tab_Size), 0)
		}
	}
}

func renderString(font *ttf.Font, val string, col sdl.Color, smooth bool) *sdl.Surface {
	if smooth {
		text, err := font.RenderUTF8_Blended(val, col)
		if err != nil {
			panic(err)
		}
		return text
	} else {
		text, err := font.RenderUTF8_Solid(val, col)
		if err != nil {
			panic(err)
		}
		return text
	}
	return nil
}

func (b *Buffer) Update() {
	prev_x := b.curs.x
	prev_y := b.curs.y

	if b.inputHandler == nil {
		panic("help")
	}

	if b.inputHandler.Event != nil {
		switch t := b.inputHandler.Event.(type) {
		case *sdl.TextInputEvent:
			b.processTextInput(t)
		case *sdl.KeyDownEvent:
			b.processActionKey(t)
		}
	}

	if b.curs.x != prev_x || b.curs.y != prev_y {
		should_draw = true
		should_flash = false
		reset_timer = sdl.GetTicks()
	}

	if !should_flash && sdl.GetTicks()-reset_timer > b.cfg.Editor.Cursor_Reset_Delay {
		should_flash = true
	}

	if sdl.GetTicks()-timer > b.cfg.Editor.Cursor_Flash_Rate && (should_flash && b.cfg.Editor.Flash_Cursor) {
		timer = sdl.GetTicks()
		should_draw = !should_draw
	}
}

var last_w, last_h int32
var TEXTURE_CACHE map[rune]*sdl.Texture = map[rune]*sdl.Texture{}

func (b *Buffer) OnRender(ctx *sdl.Renderer) {

	// render the ol' cursor
	if should_draw && b.cfg.Editor.Draw_Cursor {
		gfx.SetDrawColorHex(ctx, 0x657B83)
		ctx.FillRect(&sdl.Rect{
			b.x + (int32(b.curs.rx)+1)*last_w,
			b.y + int32(b.curs.ry)*last_h,
			last_w,
			last_h,
		})
	}

	// TODO(Felix): cull this so that
	// we dont render lines we cant see.

	var y_col int32
	for _, rope := range b.contents {
		// this is because if we had the following
		// text input:
		//
		// Foo
		// _			<-- underscore is a space!
		// Blah
		// and we delete that underscore... it causes
		// a panic because there are no characters in
		// the empty string!
		if rope.Len() == 0 {
			// even though the string is empty
			// we still need to offset it by a line
			y_col += 1
			continue
		}

		var x_col int32
		for _, char := range rope.String() {
			switch char {
			case '\n':
				x_col = 0
				y_col += 1
				continue
			case '\t':
				x_col += b.cfg.Editor.Tab_Size
				continue
			}

			char_colour := 0x7a7a7a
			if b.curs.x == int(x_col) && b.curs.y == int(y_col) {
				char_colour = 0xff00ff
			}

			x_col += 1

			text := renderString(b.font, string(char), gfx.HexColor(uint32(char_colour)), true)
			defer text.Free()

			last_w = text.W
			last_h = text.H

			texture, ok := TEXTURE_CACHE[char]
			if !ok {
				// can't find it in the cache so we
				// load and then cache it.
				texture, _ = ctx.CreateTextureFromSurface(text)
				TEXTURE_CACHE[char] = texture
			}

			// FIXME still kinda slow
			// we can also cull so that
			// we don't render things that aren't
			// visible outside of the component
			ctx.Copy(texture, nil, &sdl.Rect{
				b.x + (x_col * text.W),
				b.y + (y_col * text.H),
				text.W,
				text.H,
			})
		}

		y_col += 1
	}
}
<commit_msg>Aliasing configuration now acted upon<commit_after>package gui

import (
	"strings"
	"unicode/utf8"

	"github.com/felixangell/nate/cfg"
	"github.com/felixangell/nate/gfx"
	"github.com/veandco/go-sdl2/sdl"
	"github.com/veandco/go-sdl2/sdl_ttf"
	"github.com/vinzmay/go-rope"
)

var (
	timer        uint32 = 0
	reset_timer  uint32 = 0
	should_draw  bool   = true
	should_flash bool
)

type Buffer struct {
	BaseComponent
	font     *ttf.Font
	contents []*rope.Rope
	curs     *Cursor
	cfg      *cfg.TomlConfig
}

func NewBuffer(conf *cfg.TomlConfig) *Buffer {
	font, err := ttf.OpenFont("./res/firacode.ttf", 24)
	if err != nil {
		panic(err)
	}

	config := conf
	if config == nil {
		config = cfg.NewDefaultConfig()
	}

	buff := &Buffer{
		contents: []*rope.Rope{},
		font:     font,
		curs:     &Cursor{},
		cfg:      config,
	}
	buff.appendLine("hello! مرحبا 世界.")
	return buff
}

func (b *Buffer) Dispose() {
	for _, texture := range TEXTURE_CACHE {
		texture.Destroy()
	}
}

func (b *Buffer) Init() {}

func (b *Buffer) appendLine(val string) {
	b.contents = append(b.contents, rope.New(val))
	b.curs.move(len(val), 0)
}

func (b *Buffer) processTextInput(t *sdl.TextInputEvent) {
	// TODO: how the fuck do decode this properly?
	rawVal, size := utf8.DecodeLastRune(t.Text[:1])
	if rawVal == utf8.RuneError || size == 0 {
		return
	}

	b.contents[b.curs.y] = b.contents[b.curs.y].Insert(b.curs.x, string(rawVal))
	b.curs.move(1, 0)
}

func (b *Buffer) processActionKey(t *sdl.KeyDownEvent) {
	switch t.Keysym.Scancode {
	case sdl.SCANCODE_RETURN:
		initial_x := b.curs.x
		prevLineLen := b.contents[b.curs.y].Len()

		var newRope *rope.Rope
		if initial_x < prevLineLen && initial_x > 0 {
			left, right := b.contents[b.curs.y].Split(initial_x)
			newRope = right
			b.contents[b.curs.y] = left
		} else if initial_x == 0 {
			b.contents = append(b.contents, new(rope.Rope))      // grow
			copy(b.contents[b.curs.y+1:], b.contents[b.curs.y:]) // shift
			b.contents[b.curs.y] = new(rope.Rope)                // set
			b.curs.move(0, 1)
			return
		} else {
			newRope = rope.New(" ")
		}

		b.curs.move(0, 1)
		for x := 0; x < initial_x; x++ {
			// TODO(Felix): there's a bug here where
			// this doesn't account for the rendered x
			// position when we use tabs as tabs and not spaces
			b.curs.move(-1, 0)
		}
		b.contents = append(b.contents, newRope)
	case sdl.SCANCODE_BACKSPACE:
		if b.curs.x > 0 {
			offs := -1
			if !b.cfg.Editor.Tabs_Are_Spaces {
				if b.contents[b.curs.y].Index(b.curs.x) == '\t' {
					offs = int(-b.cfg.Editor.Tab_Size)
				}
			} else if b.cfg.Editor.Hungry_Backspace && b.curs.x >= int(b.cfg.Editor.Tab_Size) {
				// FIXME wtf how does Substr even work
				// cut out the last {TAB_SIZE} amount of characters
				// and check em
				tabSize := int(b.cfg.Editor.Tab_Size)
				lastTabSizeChars := b.contents[b.curs.y].Substr(b.curs.x+1-tabSize, tabSize).String()
				artificialTab := string(make([]rune, tabSize, ' '))
				if strings.Compare(lastTabSizeChars, artificialTab) == 0 {
					// delete {TAB_SIZE} amount of characters
					// from the cursors x pos
					for i := 0; i < int(b.cfg.Editor.Tab_Size); i++ {
						b.contents[b.curs.y] = b.contents[b.curs.y].Delete(b.curs.x, 1)
						b.curs.move(-1, 0)
					}
					break
				}
			}

			b.contents[b.curs.y] = b.contents[b.curs.y].Delete(b.curs.x, 1)
			b.curs.moveRender(-1, 0, offs, 0)
		} else if b.curs.x == 0 && b.curs.y > 0 {
			// start of line, wrap to previous
			// two cases here:

			// the line_len is zero, in which case
			// we delete the line and go to the end
			// of the previous line
			if b.contents[b.curs.y].Len() == 0 {
				b.curs.move(b.contents[b.curs.y-1].Len(), -1)
				// FIXME, delete from the curs.y dont pop!
				b.contents = b.contents[:len(b.contents)-1]
				return
			}

			// TODO(Felix): handle all the edge cases here...

			// or, the line has characters, so we join
			// that line with the previous line
			prevLineLen := b.contents[b.curs.y-1].Len()
			b.contents[b.curs.y-1] = b.contents[b.curs.y-1].Concat(b.contents[b.curs.y])
			b.contents = append(b.contents[:b.curs.y], b.contents[b.curs.y+1:]...)
			b.curs.move(prevLineLen, -1)
		}
	case sdl.SCANCODE_RIGHT:
		currLineLength := b.contents[b.curs.y].Len()
		if b.curs.x >= currLineLength && b.curs.y < len(b.contents)-1 {
			// we're at the end of the line and we have
			// some lines after, let's wrap around
			b.curs.move(0, 1)
			b.curs.move(-currLineLength, 0)
		} else if b.curs.x < b.contents[b.curs.y].Len() {
			// we have characters to the right, let's move along
			b.curs.move(1, 0)
		}
	case sdl.SCANCODE_LEFT:
		if b.curs.x == 0 && b.curs.y > 0 {
			b.curs.move(b.contents[b.curs.y-1].Len(), -1)

		} else if b.curs.x > 0 {
			b.curs.move(-1, 0)
		}
	case sdl.SCANCODE_TAB:
		if b.cfg.Editor.Tabs_Are_Spaces {
			// make an empty rune array of TAB_SIZE, cast to string
			// and insert it.
			b.contents[b.curs.y] = b.contents[b.curs.y].Insert(b.curs.x, "    ")
			b.curs.move(int(b.cfg.Editor.Tab_Size), 0)
		} else {
			b.contents[b.curs.y] = b.contents[b.curs.y].Insert(b.curs.x, string('\t'))
			// the actual position is + 1, but we make it
			// move by TAB_SIZE characters on the view.
			b.curs.moveRender(1, 0, int(b.cfg.Editor.Tab_Size), 0)
		}
	}
}

func renderString(font *ttf.Font, val string, col sdl.Color, smooth bool) *sdl.Surface {
	if smooth {
		text, err := font.RenderUTF8_Blended(val, col)
		if err != nil {
			panic(err)
		}
		return text
	} else {
		text, err := font.RenderUTF8_Solid(val, col)
		if err != nil {
			panic(err)
		}
		return text
	}
	return nil
}

func (b *Buffer) Update() {
	prev_x := b.curs.x
	prev_y := b.curs.y

	if b.inputHandler == nil {
		panic("help")
	}

	if b.inputHandler.Event != nil {
		switch t := b.inputHandler.Event.(type) {
		case *sdl.TextInputEvent:
			b.processTextInput(t)
		case *sdl.KeyDownEvent:
			b.processActionKey(t)
		}
	}

	if b.curs.x != prev_x || b.curs.y != prev_y {
		should_draw = true
		should_flash = false
		reset_timer = sdl.GetTicks()
	}

	if !should_flash && sdl.GetTicks()-reset_timer > b.cfg.Editor.Cursor_Reset_Delay {
		should_flash = true
	}

	if sdl.GetTicks()-timer > b.cfg.Editor.Cursor_Flash_Rate && (should_flash && b.cfg.Editor.Flash_Cursor) {
		timer = sdl.GetTicks()
		should_draw = !should_draw
	}
}

var last_w, last_h int32
var TEXTURE_CACHE map[rune]*sdl.Texture = map[rune]*sdl.Texture{}

func (b *Buffer) OnRender(ctx *sdl.Renderer) {

	// render the ol' cursor
	if should_draw && b.cfg.Editor.Draw_Cursor {
		gfx.SetDrawColorHex(ctx, 0x657B83)
		ctx.FillRect(&sdl.Rect{
			b.x + (int32(b.curs.rx)+1)*last_w,
			b.y + int32(b.curs.ry)*last_h,
			last_w,
			last_h,
		})
	}

	// TODO(Felix): cull this so that
	// we dont render lines we cant see.

	var y_col int32
	for _, rope := range b.contents {
		// this is because if we had the following
		// text input:
		//
		// Foo
		// _			<-- underscore is a space!
		// Blah
		// and we delete that underscore... it causes
		// a panic because there are no characters in
		// the empty string!
		if rope.Len() == 0 {
			// even though the string is empty
			// we still need to offset it by a line
			y_col += 1
			continue
		}

		var x_col int32
		for _, char := range rope.String() {
			switch char {
			case '\n':
				x_col = 0
				y_col += 1
				continue
			case '\t':
				x_col += b.cfg.Editor.Tab_Size
				continue
			}

			char_colour := 0x7a7a7a
			if b.curs.x == int(x_col) && b.curs.y == int(y_col) {
				char_colour = 0xff00ff
			}

			x_col += 1

			text := renderString(b.font, string(char), gfx.HexColor(uint32(char_colour)), b.cfg.Editor.Aliased)
			defer text.Free()

			last_w = text.W
			last_h = text.H

			texture, ok := TEXTURE_CACHE[char]
			if !ok {
				// can't find it in the cache so we
				// load and then cache it.
				texture, _ = ctx.CreateTextureFromSurface(text)
				TEXTURE_CACHE[char] = texture
			}

			// FIXME still kinda slow
			// we can also cull so that
			// we don't render things that aren't
			// visible outside of the component
			ctx.Copy(texture, nil, &sdl.Rect{
				b.x + (x_col * text.W),
				b.y + (y_col * text.H),
				text.W,
				text.H,
			})
		}

		y_col += 1
	}
}
<|endoftext|>


<commit_before>package handler

import (
	"context"
	"encoding/json"

	"cloud.google.com/go/pubsub"
	"github.com/checkr/flagr/pkg/config"
	"github.com/checkr/flagr/swagger_gen/models"
	"google.golang.org/api/option"

	"github.com/sirupsen/logrus"
)

type pubsubRecorder struct {
	enabled  bool
	producer *pubsub.Client
	topic    *pubsub.Topic
}

// NewPubsubRecorder creates a new Pubsub recorder
var NewPubsubRecorder = func() DataRecorder {
	client, err := pubsub.NewClient(
		context.Background(),
		config.Config.RecorderPubsubProjectID,
		option.WithCredentialsFile(config.Config.RecorderPubsubKeyFile),
	)
	if err != nil {
		logrus.WithField("pubsub_error", err).Error("error getting pubsub client")
	}

	return &pubsubRecorder{
		producer: client,
		topic:    client.Topic(config.Config.RecorderPubsubTopicName),
		enabled:  config.Config.RecorderEnabled,
	}
}

func (p *pubsubRecorder) AsyncRecord(r *models.EvalResult) {
	if !p.enabled {
		return
	}

	pr := &pubsubEvalResult{
		EvalResult: r,
	}

	payload, err := pr.Payload()
	if err != nil {
		logrus.WithField("pubsub_error", err).Error("error marshaling")
	}

	messageFrame := pubsubMessageFrame{
		Payload:   string(payload),
		Encrypted: false,
	}

	_, err = messageFrame.encode()
	if err != nil {
		logrus.WithField("pubsub_error", err).Error("error marshaling")
	}

	ctx := context.Background()
	res := p.topic.Publish(ctx, &pubsub.Message{Data: payload})
	if config.Config.RecorderPubsubVerbose {
		id, err := res.Get(ctx)
		if err != nil {
			logrus.WithFields(logrus.Fields{"pubsub_error": err, "id": id}).Error("error pushing to pubsub")
		}
	}
}

type pubsubEvalResult struct {
	*models.EvalResult
}

type pubsubMessageFrame struct {
	Payload   string `json:"payload"`
	Encrypted bool   `json:"encrypted"`
}

func (pmf *pubsubMessageFrame) encode() ([]byte, error) {
	return json.MarshalIndent(pmf, "", "  ")
}

// Payload marshals the EvalResult
func (r *pubsubEvalResult) Payload() ([]byte, error) {
	return r.EvalResult.MarshalBinary()
}
<commit_msg>fixing comments<commit_after>package handler

import (
	"context"
	"encoding/json"
	"time"

	"cloud.google.com/go/pubsub"
	"github.com/checkr/flagr/pkg/config"
	"github.com/checkr/flagr/swagger_gen/models"
	"google.golang.org/api/option"

	"github.com/sirupsen/logrus"
)

type pubsubRecorder struct {
	enabled  bool
	producer *pubsub.Client
	topic    *pubsub.Topic
}

// NewPubsubRecorder creates a new Pubsub recorder
var NewPubsubRecorder = func() DataRecorder {
	client, err := pubsub.NewClient(
		context.Background(),
		config.Config.RecorderPubsubProjectID,
		option.WithCredentialsFile(config.Config.RecorderPubsubKeyFile),
	)
	if err != nil {
		logrus.WithField("pubsub_error", err).Fatal("error getting pubsub client")
	}

	return &pubsubRecorder{
		producer: client,
		topic:    client.Topic(config.Config.RecorderPubsubTopicName),
		enabled:  config.Config.RecorderEnabled,
	}
}

func (p *pubsubRecorder) AsyncRecord(r *models.EvalResult) {
	if !p.enabled {
		return
	}

	pr := &pubsubEvalResult{
		EvalResult: r,
	}

	payload, err := pr.Payload()
	if err != nil {
		logrus.WithField("pubsub_error", err).Error("error marshaling")
	}

	messageFrame := pubsubMessageFrame{
		Payload:   string(payload),
		Encrypted: false,
	}

	_, err = messageFrame.encode()
	if err != nil {
		logrus.WithField("pubsub_error", err).Error("error marshaling")
	}

	ctx := context.WithTimeout(context.Background(), 10*time.Second) // TODO: make it configurable
	res := p.topic.Publish(ctx, &pubsub.Message{Data: payload})
	if config.Config.RecorderPubsubVerbose {
		id, err := res.Get(ctx)
		if err != nil {
			logrus.WithFields(logrus.Fields{"pubsub_error": err, "id": id}).Error("error pushing to pubsub")
		}
	}
}

type pubsubEvalResult struct {
	*models.EvalResult
}

type pubsubMessageFrame struct {
	Payload   string `json:"payload"`
	Encrypted bool   `json:"encrypted"`
}

func (pmf *pubsubMessageFrame) encode() ([]byte, error) {
	return json.MarshalIndent(pmf, "", "  ")
}

// Payload marshals the EvalResult
func (r *pubsubEvalResult) Payload() ([]byte, error) {
	return r.EvalResult.MarshalBinary()
}
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package schema

import (
	"fmt"
	"strings"
)

// ParseResourceArg takes the common style of string which may be either `resource.group.com` or `resource.version.group.com`
// and parses it out into both possibilities.  This code takes no responsibility for knowing which representation was intended
// but with a knowledge of all GroupVersions, calling code can take a very good guess.  If there are only two segments, then
// `*GroupVersionResource` is nil.
// `resource.group.com` -> `group=com, version=group, resource=resource` and `group=group.com, resource=resource`
func ParseResourceArg(arg string) (*GroupVersionResource, GroupResource) {
	var gvr *GroupVersionResource
	if strings.Count(arg, ".") >= 2 {
		s := strings.SplitN(arg, ".", 3)
		gvr = &GroupVersionResource{Group: s[2], Version: s[1], Resource: s[0]}
	}

	return gvr, ParseGroupResource(arg)
}

// ParseKindArg takes the common style of string which may be either `Kind.group.com` or `Kind.version.group.com`
// and parses it out into both possibilities. This code takes no responsibility for knowing which representation was intended
// but with a knowledge of all GroupKinds, calling code can take a very good guess. If there are only two segments, then
// `*GroupVersionResource` is nil.
// `Kind.group.com` -> `group=com, version=group, kind=Kind` and `group=group.com, kind=Kind`
func ParseKindArg(arg string) (*GroupVersionKind, GroupKind) {
	var gvk *GroupVersionKind
	if strings.Count(arg, ".") >= 2 {
		s := strings.SplitN(arg, ".", 3)
		gvk = &GroupVersionKind{Group: s[2], Version: s[1], Kind: s[0]}
	}

	return gvk, ParseGroupKind(arg)
}

// GroupResource specifies a Group and a Resource, but does not force a version.  This is useful for identifying
// concepts during lookup stages without having partially valid types
type GroupResource struct {
	Group    string
	Resource string
}

func (gr GroupResource) WithVersion(version string) GroupVersionResource {
	return GroupVersionResource{Group: gr.Group, Version: version, Resource: gr.Resource}
}

func (gr GroupResource) Empty() bool {
	return len(gr.Group) == 0 && len(gr.Resource) == 0
}

func (gr *GroupResource) String() string {
	if len(gr.Group) == 0 {
		return gr.Resource
	}
	return gr.Resource + "." + gr.Group
}

func ParseGroupKind(gk string) GroupKind {
	i := strings.Index(gk, ".")
	if i == -1 {
		return GroupKind{Kind: gk}
	}

	return GroupKind{Group: gk[i+1:], Kind: gk[:i]}
}

// ParseGroupResource turns "resource.group" string into a GroupResource struct.  Empty strings are allowed
// for each field.
func ParseGroupResource(gr string) GroupResource {
	if i := strings.Index(gr, "."); i == -1 {
		return GroupResource{Resource: gr}
	} else {
		return GroupResource{Group: gr[i+1:], Resource: gr[:i]}
	}
}

// GroupVersionResource unambiguously identifies a resource.  It doesn't anonymously include GroupVersion
// to avoid automatic coercion.  It doesn't use a GroupVersion to avoid custom marshalling
type GroupVersionResource struct {
	Group    string
	Version  string
	Resource string
}

func (gvr GroupVersionResource) Empty() bool {
	return len(gvr.Group) == 0 && len(gvr.Version) == 0 && len(gvr.Resource) == 0
}

func (gvr GroupVersionResource) GroupResource() GroupResource {
	return GroupResource{Group: gvr.Group, Resource: gvr.Resource}
}

func (gvr GroupVersionResource) GroupVersion() GroupVersion {
	return GroupVersion{Group: gvr.Group, Version: gvr.Version}
}

func (gvr *GroupVersionResource) String() string {
	return strings.Join([]string{gvr.Group, "/", gvr.Version, ", Resource=", gvr.Resource}, "")
}

// GroupKind specifies a Group and a Kind, but does not force a version.  This is useful for identifying
// concepts during lookup stages without having partially valid types
type GroupKind struct {
	Group string
	Kind  string
}

func (gk GroupKind) Empty() bool {
	return len(gk.Group) == 0 && len(gk.Kind) == 0
}

func (gk GroupKind) WithVersion(version string) GroupVersionKind {
	return GroupVersionKind{Group: gk.Group, Version: version, Kind: gk.Kind}
}

func (gk *GroupKind) String() string {
	if len(gk.Group) == 0 {
		return gk.Kind
	}
	return gk.Kind + "." + gk.Group
}

// GroupVersionKind unambiguously identifies a kind.  It doesn't anonymously include GroupVersion
// to avoid automatic coercion.  It doesn't use a GroupVersion to avoid custom marshalling
type GroupVersionKind struct {
	Group   string
	Version string
	Kind    string
}

// Empty returns true if group, version, and kind are empty
func (gvk GroupVersionKind) Empty() bool {
	return len(gvk.Group) == 0 && len(gvk.Version) == 0 && len(gvk.Kind) == 0
}

func (gvk GroupVersionKind) GroupKind() GroupKind {
	return GroupKind{Group: gvk.Group, Kind: gvk.Kind}
}

func (gvk GroupVersionKind) GroupVersion() GroupVersion {
	return GroupVersion{Group: gvk.Group, Version: gvk.Version}
}

func (gvk GroupVersionKind) String() string {
	return gvk.Group + "/" + gvk.Version + ", Kind=" + gvk.Kind
}

// GroupVersion contains the "group" and the "version", which uniquely identifies the API.
type GroupVersion struct {
	Group   string
	Version string
}

// Empty returns true if group and version are empty
func (gv GroupVersion) Empty() bool {
	return len(gv.Group) == 0 && len(gv.Version) == 0
}

// String puts "group" and "version" into a single "group/version" string. For the legacy v1
// it returns "v1".
func (gv GroupVersion) String() string {
	// special case the internal apiVersion for the legacy kube types
	if gv.Empty() {
		return ""
	}

	// special case of "v1" for backward compatibility
	if len(gv.Group) == 0 && gv.Version == "v1" {
		return gv.Version
	}
	if len(gv.Group) > 0 {
		return gv.Group + "/" + gv.Version
	}
	return gv.Version
}

// KindForGroupVersionKinds identifies the preferred GroupVersionKind out of a list. It returns ok false
// if none of the options match the group. It prefers a match to group and version over just group.
// TODO: Move GroupVersion to a package under pkg/runtime, since it's used by scheme.
// TODO: Introduce an adapter type between GroupVersion and runtime.GroupVersioner, and use LegacyCodec(GroupVersion)
//   in fewer places.
func (gv GroupVersion) KindForGroupVersionKinds(kinds []GroupVersionKind) (target GroupVersionKind, ok bool) {
	for _, gvk := range kinds {
		if gvk.Group == gv.Group && gvk.Version == gv.Version {
			return gvk, true
		}
	}
	for _, gvk := range kinds {
		if gvk.Group == gv.Group {
			return gv.WithKind(gvk.Kind), true
		}
	}
	return GroupVersionKind{}, false
}

// ParseGroupVersion turns "group/version" string into a GroupVersion struct. It reports error
// if it cannot parse the string.
func ParseGroupVersion(gv string) (GroupVersion, error) {
	// this can be the internal version for the legacy kube types
	// TODO once we've cleared the last uses as strings, this special case should be removed.
	if (len(gv) == 0) || (gv == "/") {
		return GroupVersion{}, nil
	}

	switch strings.Count(gv, "/") {
	case 0:
		return GroupVersion{"", gv}, nil
	case 1:
		i := strings.Index(gv, "/")
		return GroupVersion{gv[:i], gv[i+1:]}, nil
	default:
		return GroupVersion{}, fmt.Errorf("unexpected GroupVersion string: %v", gv)
	}
}

// WithKind creates a GroupVersionKind based on the method receiver's GroupVersion and the passed Kind.
func (gv GroupVersion) WithKind(kind string) GroupVersionKind {
	return GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind}
}

// WithResource creates a GroupVersionResource based on the method receiver's GroupVersion and the passed Resource.
func (gv GroupVersion) WithResource(resource string) GroupVersionResource {
	return GroupVersionResource{Group: gv.Group, Version: gv.Version, Resource: resource}
}

// GroupVersions can be used to represent a set of desired group versions.
// TODO: Move GroupVersions to a package under pkg/runtime, since it's used by scheme.
// TODO: Introduce an adapter type between GroupVersions and runtime.GroupVersioner, and use LegacyCodec(GroupVersion)
//   in fewer places.
type GroupVersions []GroupVersion

// KindForGroupVersionKinds identifies the preferred GroupVersionKind out of a list. It returns ok false
// if none of the options match the group.
func (gvs GroupVersions) KindForGroupVersionKinds(kinds []GroupVersionKind) (GroupVersionKind, bool) {
	var targets []GroupVersionKind
	for _, gv := range gvs {
		target, ok := gv.KindForGroupVersionKinds(kinds)
		if !ok {
			continue
		}
		targets = append(targets, target)
	}
	if len(targets) == 1 {
		return targets[0], true
	}
	if len(targets) > 1 {
		return bestMatch(kinds, targets), true
	}
	return GroupVersionKind{}, false
}

// bestMatch tries to pick best matching GroupVersionKind and falls back to the first
// found if no exact match exists.
func bestMatch(kinds []GroupVersionKind, targets []GroupVersionKind) GroupVersionKind {
	for _, gvk := range targets {
		for _, k := range kinds {
			if k == gvk {
				return k
			}
		}
	}
	return targets[0]
}

// ToAPIVersionAndKind is a convenience method for satisfying runtime.Object on types that
// do not use TypeMeta.
func (gvk *GroupVersionKind) ToAPIVersionAndKind() (string, string) {
	if gvk == nil {
		return "", ""
	}
	return gvk.GroupVersion().String(), gvk.Kind
}

// FromAPIVersionAndKind returns a GVK representing the provided fields for types that
// do not use TypeMeta. This method exists to support test types and legacy serializations
// that have a distinct group and kind.
// TODO: further reduce usage of this method.
func FromAPIVersionAndKind(apiVersion, kind string) GroupVersionKind {
	if gv, err := ParseGroupVersion(apiVersion); err == nil {
		return GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind}
	}
	return GroupVersionKind{Kind: kind}
}
<commit_msg>apimachinery: cleanup if...else statement<commit_after>/*
Copyright 2015 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package schema

import (
	"fmt"
	"strings"
)

// ParseResourceArg takes the common style of string which may be either `resource.group.com` or `resource.version.group.com`
// and parses it out into both possibilities.  This code takes no responsibility for knowing which representation was intended
// but with a knowledge of all GroupVersions, calling code can take a very good guess.  If there are only two segments, then
// `*GroupVersionResource` is nil.
// `resource.group.com` -> `group=com, version=group, resource=resource` and `group=group.com, resource=resource`
func ParseResourceArg(arg string) (*GroupVersionResource, GroupResource) {
	var gvr *GroupVersionResource
	if strings.Count(arg, ".") >= 2 {
		s := strings.SplitN(arg, ".", 3)
		gvr = &GroupVersionResource{Group: s[2], Version: s[1], Resource: s[0]}
	}

	return gvr, ParseGroupResource(arg)
}

// ParseKindArg takes the common style of string which may be either `Kind.group.com` or `Kind.version.group.com`
// and parses it out into both possibilities. This code takes no responsibility for knowing which representation was intended
// but with a knowledge of all GroupKinds, calling code can take a very good guess. If there are only two segments, then
// `*GroupVersionResource` is nil.
// `Kind.group.com` -> `group=com, version=group, kind=Kind` and `group=group.com, kind=Kind`
func ParseKindArg(arg string) (*GroupVersionKind, GroupKind) {
	var gvk *GroupVersionKind
	if strings.Count(arg, ".") >= 2 {
		s := strings.SplitN(arg, ".", 3)
		gvk = &GroupVersionKind{Group: s[2], Version: s[1], Kind: s[0]}
	}

	return gvk, ParseGroupKind(arg)
}

// GroupResource specifies a Group and a Resource, but does not force a version.  This is useful for identifying
// concepts during lookup stages without having partially valid types
type GroupResource struct {
	Group    string
	Resource string
}

func (gr GroupResource) WithVersion(version string) GroupVersionResource {
	return GroupVersionResource{Group: gr.Group, Version: version, Resource: gr.Resource}
}

func (gr GroupResource) Empty() bool {
	return len(gr.Group) == 0 && len(gr.Resource) == 0
}

func (gr *GroupResource) String() string {
	if len(gr.Group) == 0 {
		return gr.Resource
	}
	return gr.Resource + "." + gr.Group
}

func ParseGroupKind(gk string) GroupKind {
	i := strings.Index(gk, ".")
	if i == -1 {
		return GroupKind{Kind: gk}
	}

	return GroupKind{Group: gk[i+1:], Kind: gk[:i]}
}

// ParseGroupResource turns "resource.group" string into a GroupResource struct.  Empty strings are allowed
// for each field.
func ParseGroupResource(gr string) GroupResource {
	if i := strings.Index(gr, "."); i >= 0 {
		return GroupResource{Group: gr[i+1:], Resource: gr[:i]}
	}
	return GroupResource{Resource: gr}
}

// GroupVersionResource unambiguously identifies a resource.  It doesn't anonymously include GroupVersion
// to avoid automatic coercion.  It doesn't use a GroupVersion to avoid custom marshalling
type GroupVersionResource struct {
	Group    string
	Version  string
	Resource string
}

func (gvr GroupVersionResource) Empty() bool {
	return len(gvr.Group) == 0 && len(gvr.Version) == 0 && len(gvr.Resource) == 0
}

func (gvr GroupVersionResource) GroupResource() GroupResource {
	return GroupResource{Group: gvr.Group, Resource: gvr.Resource}
}

func (gvr GroupVersionResource) GroupVersion() GroupVersion {
	return GroupVersion{Group: gvr.Group, Version: gvr.Version}
}

func (gvr *GroupVersionResource) String() string {
	return strings.Join([]string{gvr.Group, "/", gvr.Version, ", Resource=", gvr.Resource}, "")
}

// GroupKind specifies a Group and a Kind, but does not force a version.  This is useful for identifying
// concepts during lookup stages without having partially valid types
type GroupKind struct {
	Group string
	Kind  string
}

func (gk GroupKind) Empty() bool {
	return len(gk.Group) == 0 && len(gk.Kind) == 0
}

func (gk GroupKind) WithVersion(version string) GroupVersionKind {
	return GroupVersionKind{Group: gk.Group, Version: version, Kind: gk.Kind}
}

func (gk *GroupKind) String() string {
	if len(gk.Group) == 0 {
		return gk.Kind
	}
	return gk.Kind + "." + gk.Group
}

// GroupVersionKind unambiguously identifies a kind.  It doesn't anonymously include GroupVersion
// to avoid automatic coercion.  It doesn't use a GroupVersion to avoid custom marshalling
type GroupVersionKind struct {
	Group   string
	Version string
	Kind    string
}

// Empty returns true if group, version, and kind are empty
func (gvk GroupVersionKind) Empty() bool {
	return len(gvk.Group) == 0 && len(gvk.Version) == 0 && len(gvk.Kind) == 0
}

func (gvk GroupVersionKind) GroupKind() GroupKind {
	return GroupKind{Group: gvk.Group, Kind: gvk.Kind}
}

func (gvk GroupVersionKind) GroupVersion() GroupVersion {
	return GroupVersion{Group: gvk.Group, Version: gvk.Version}
}

func (gvk GroupVersionKind) String() string {
	return gvk.Group + "/" + gvk.Version + ", Kind=" + gvk.Kind
}

// GroupVersion contains the "group" and the "version", which uniquely identifies the API.
type GroupVersion struct {
	Group   string
	Version string
}

// Empty returns true if group and version are empty
func (gv GroupVersion) Empty() bool {
	return len(gv.Group) == 0 && len(gv.Version) == 0
}

// String puts "group" and "version" into a single "group/version" string. For the legacy v1
// it returns "v1".
func (gv GroupVersion) String() string {
	// special case the internal apiVersion for the legacy kube types
	if gv.Empty() {
		return ""
	}

	// special case of "v1" for backward compatibility
	if len(gv.Group) == 0 && gv.Version == "v1" {
		return gv.Version
	}
	if len(gv.Group) > 0 {
		return gv.Group + "/" + gv.Version
	}
	return gv.Version
}

// KindForGroupVersionKinds identifies the preferred GroupVersionKind out of a list. It returns ok false
// if none of the options match the group. It prefers a match to group and version over just group.
// TODO: Move GroupVersion to a package under pkg/runtime, since it's used by scheme.
// TODO: Introduce an adapter type between GroupVersion and runtime.GroupVersioner, and use LegacyCodec(GroupVersion)
//   in fewer places.
func (gv GroupVersion) KindForGroupVersionKinds(kinds []GroupVersionKind) (target GroupVersionKind, ok bool) {
	for _, gvk := range kinds {
		if gvk.Group == gv.Group && gvk.Version == gv.Version {
			return gvk, true
		}
	}
	for _, gvk := range kinds {
		if gvk.Group == gv.Group {
			return gv.WithKind(gvk.Kind), true
		}
	}
	return GroupVersionKind{}, false
}

// ParseGroupVersion turns "group/version" string into a GroupVersion struct. It reports error
// if it cannot parse the string.
func ParseGroupVersion(gv string) (GroupVersion, error) {
	// this can be the internal version for the legacy kube types
	// TODO once we've cleared the last uses as strings, this special case should be removed.
	if (len(gv) == 0) || (gv == "/") {
		return GroupVersion{}, nil
	}

	switch strings.Count(gv, "/") {
	case 0:
		return GroupVersion{"", gv}, nil
	case 1:
		i := strings.Index(gv, "/")
		return GroupVersion{gv[:i], gv[i+1:]}, nil
	default:
		return GroupVersion{}, fmt.Errorf("unexpected GroupVersion string: %v", gv)
	}
}

// WithKind creates a GroupVersionKind based on the method receiver's GroupVersion and the passed Kind.
func (gv GroupVersion) WithKind(kind string) GroupVersionKind {
	return GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind}
}

// WithResource creates a GroupVersionResource based on the method receiver's GroupVersion and the passed Resource.
func (gv GroupVersion) WithResource(resource string) GroupVersionResource {
	return GroupVersionResource{Group: gv.Group, Version: gv.Version, Resource: resource}
}

// GroupVersions can be used to represent a set of desired group versions.
// TODO: Move GroupVersions to a package under pkg/runtime, since it's used by scheme.
// TODO: Introduce an adapter type between GroupVersions and runtime.GroupVersioner, and use LegacyCodec(GroupVersion)
//   in fewer places.
type GroupVersions []GroupVersion

// KindForGroupVersionKinds identifies the preferred GroupVersionKind out of a list. It returns ok false
// if none of the options match the group.
func (gvs GroupVersions) KindForGroupVersionKinds(kinds []GroupVersionKind) (GroupVersionKind, bool) {
	var targets []GroupVersionKind
	for _, gv := range gvs {
		target, ok := gv.KindForGroupVersionKinds(kinds)
		if !ok {
			continue
		}
		targets = append(targets, target)
	}
	if len(targets) == 1 {
		return targets[0], true
	}
	if len(targets) > 1 {
		return bestMatch(kinds, targets), true
	}
	return GroupVersionKind{}, false
}

// bestMatch tries to pick best matching GroupVersionKind and falls back to the first
// found if no exact match exists.
func bestMatch(kinds []GroupVersionKind, targets []GroupVersionKind) GroupVersionKind {
	for _, gvk := range targets {
		for _, k := range kinds {
			if k == gvk {
				return k
			}
		}
	}
	return targets[0]
}

// ToAPIVersionAndKind is a convenience method for satisfying runtime.Object on types that
// do not use TypeMeta.
func (gvk *GroupVersionKind) ToAPIVersionAndKind() (string, string) {
	if gvk == nil {
		return "", ""
	}
	return gvk.GroupVersion().String(), gvk.Kind
}

// FromAPIVersionAndKind returns a GVK representing the provided fields for types that
// do not use TypeMeta. This method exists to support test types and legacy serializations
// that have a distinct group and kind.
// TODO: further reduce usage of this method.
func FromAPIVersionAndKind(apiVersion, kind string) GroupVersionKind {
	if gv, err := ParseGroupVersion(apiVersion); err == nil {
		return GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind}
	}
	return GroupVersionKind{Kind: kind}
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package scaleio

import (
	"encoding/gob"
	"os"
	"path"
	"reflect"
	"testing"

	utiltesting "k8s.io/client-go/util/testing"
	api "k8s.io/kubernetes/pkg/api/v1"
)

var (
	vol = &api.Volume{
		Name: testSioVolName,
		VolumeSource: api.VolumeSource{
			ScaleIO: &api.ScaleIOVolumeSource{
				Gateway:          "http://test.scaleio:1111",
				System:           "sio",
				ProtectionDomain: "defaultPD",
				StoragePool:      "defaultSP",
				VolumeName:       "test-vol",
				FSType:           "ext4",
				SecretRef:        &api.LocalObjectReference{Name: "test-secret"},
			},
		},
	}

	config = map[string]string{
		confKey.system:           "sio",
		confKey.gateway:          "http://sio/",
		confKey.volSpecName:      testSioVolName,
		confKey.volumeName:       "sio-vol",
		confKey.secretRef:        "sio-secret",
		confKey.protectionDomain: "defaultPD",
		confKey.storagePool:      "deraultSP",
		confKey.fsType:           "xfs",
		confKey.readOnly:         "true",
	}

	testConfigFile = "conf.dat"
)

func TestUtilMapVolumeSource(t *testing.T) {
	data := make(map[string]string)
	mapVolumeSource(data, vol.VolumeSource.ScaleIO)
	if data[confKey.gateway] != "http://test.scaleio:1111" {
		t.Error("Unexpected gateway value")
	}
	if data[confKey.system] != "sio" {
		t.Error("Unexpected system value")
	}
	if data[confKey.protectionDomain] != "defaultPD" {
		t.Error("Unexpected protection domain value")
	}
	if data[confKey.storagePool] != "defaultSP" {
		t.Error("Unexpected storage pool value")
	}
	if data[confKey.volumeName] != "test-vol" {
		t.Error("Unexpected volume name value")
	}
	if data[confKey.fsType] != "ext4" {
		t.Error("Unexpected fstype value")
	}
	if data[confKey.secretRef] != "test-secret" {
		t.Error("Unexpected secret ref value")
	}
	if data[confKey.sslEnabled] != "false" {
		t.Error("Unexpected sslEnabled value")
	}
	if data[confKey.readOnly] != "false" {
		t.Error("Unexpected readOnly value: ", data[confKey.readOnly])
	}
}

func TestUtilValidateConfigs(t *testing.T) {
	data := map[string]string{
		confKey.secretRef: "sio-secret",
		confKey.system:    "sio",
	}
	if err := validateConfigs(data); err != gatewayNotProvidedErr {
		t.Error("Expecting error for missing gateway, but did not get it")
	}
}

func TestUtilApplyConfigDefaults(t *testing.T) {
	data := map[string]string{
		confKey.system:     "sio",
		confKey.gateway:    "http://sio/",
		confKey.volumeName: "sio-vol",
		confKey.secretRef:  "test-secret",
	}
	applyConfigDefaults(data)

	if data[confKey.gateway] != "http://sio/" {
		t.Error("Unexpected gateway value")
	}
	if data[confKey.system] != "sio" {
		t.Error("Unexpected system value")
	}
	if data[confKey.protectionDomain] != "default" {
		t.Error("Unexpected protection domain value")
	}
	if data[confKey.storagePool] != "default" {
		t.Error("Unexpected storage pool value")
	}
	if data[confKey.volumeName] != "sio-vol" {
		t.Error("Unexpected volume name value")
	}
	if data[confKey.fsType] != "xfs" {
		t.Error("Unexpected fstype value")
	}
	if data[confKey.storageMode] != "ThinProvisioned" {
		t.Error("Unexpected storage mode value")
	}
	if data[confKey.secretRef] != "test-secret" {
		t.Error("Unexpected secret ref value")
	}
	if data[confKey.sslEnabled] != "false" {
		t.Error("Unexpected sslEnabled value")
	}
	if data[confKey.readOnly] != "false" {
		t.Error("Unexpected readOnly value: ", data[confKey.readOnly])
	}
}

func TestUtilDefaultString(t *testing.T) {
	if defaultString("", "foo") != "foo" {
		t.Error("Unexpected value for default value")
	}
}

func TestUtilSaveConfig(t *testing.T) {
	tmpDir, err := utiltesting.MkTmpdir("scaleio-test")
	if err != nil {
		t.Fatalf("can't make a temp dir: %v", err)
	}
	defer os.RemoveAll(tmpDir)

	config := path.Join(tmpDir, testConfigFile)
	data := map[string]string{
		confKey.gateway:    "https://test-gateway/",
		confKey.secretRef:  "sio-secret",
		confKey.sslEnabled: "false",
	}
	if err := saveConfig(config, data); err != nil {
		t.Fatal("failed while saving data", err)
	}
	file, err := os.Open(config)
	if err != nil {
		t.Fatal("failed to open conf file: ", file)
	}
	dataRcvd := map[string]string{}
	if err := gob.NewDecoder(file).Decode(&dataRcvd); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(data, dataRcvd) {
		t.Error("we got problem, config data not the same")
	}
}

func TestUtilAttachSecret(t *testing.T) {
	plugMgr, tmpDir := newPluginMgr(t)
	defer os.RemoveAll(tmpDir)

	plug, err := plugMgr.FindPluginByName(sioPluginName)
	if err != nil {
		t.Errorf("Can't find the plugin %v", sioPluginName)
	}
	sioPlug, ok := plug.(*sioPlugin)
	if !ok {
		t.Errorf("Cannot assert plugin to be type sioPlugin")
	}

	data := make(map[string]string)
	for k, v := range config {
		data[k] = v
	}
	if err := attachSecret(sioPlug, "default", data); err != nil {
		t.Errorf("failed to setupConfigData %v", err)
	}
	if data[confKey.username] == "" {
		t.Errorf("failed to merge secret")
	}
}

func TestUtilLoadConfig(t *testing.T) {
	tmpDir, err := utiltesting.MkTmpdir("scaleio-test")
	if err != nil {
		t.Fatalf("can't make a temp dir: %v", err)
	}
	defer os.RemoveAll(tmpDir)

	configFile := path.Join(tmpDir, sioConfigFileName)

	if err := saveConfig(configFile, config); err != nil {
		t.Fatal("failed while saving data", err)
	}

	dataRcvd, err := loadConfig(configFile)
	if dataRcvd[confKey.gateway] != config[confKey.gateway] ||
		dataRcvd[confKey.system] != config[confKey.system] {
		t.Fatal("loaded config data not matching saved config data")
	}
}
<commit_msg>Fix missing close file<commit_after>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package scaleio

import (
	"encoding/gob"
	"os"
	"path"
	"reflect"
	"testing"

	utiltesting "k8s.io/client-go/util/testing"
	api "k8s.io/kubernetes/pkg/api/v1"
)

var (
	vol = &api.Volume{
		Name: testSioVolName,
		VolumeSource: api.VolumeSource{
			ScaleIO: &api.ScaleIOVolumeSource{
				Gateway:          "http://test.scaleio:1111",
				System:           "sio",
				ProtectionDomain: "defaultPD",
				StoragePool:      "defaultSP",
				VolumeName:       "test-vol",
				FSType:           "ext4",
				SecretRef:        &api.LocalObjectReference{Name: "test-secret"},
			},
		},
	}

	config = map[string]string{
		confKey.system:           "sio",
		confKey.gateway:          "http://sio/",
		confKey.volSpecName:      testSioVolName,
		confKey.volumeName:       "sio-vol",
		confKey.secretRef:        "sio-secret",
		confKey.protectionDomain: "defaultPD",
		confKey.storagePool:      "deraultSP",
		confKey.fsType:           "xfs",
		confKey.readOnly:         "true",
	}

	testConfigFile = "conf.dat"
)

func TestUtilMapVolumeSource(t *testing.T) {
	data := make(map[string]string)
	mapVolumeSource(data, vol.VolumeSource.ScaleIO)
	if data[confKey.gateway] != "http://test.scaleio:1111" {
		t.Error("Unexpected gateway value")
	}
	if data[confKey.system] != "sio" {
		t.Error("Unexpected system value")
	}
	if data[confKey.protectionDomain] != "defaultPD" {
		t.Error("Unexpected protection domain value")
	}
	if data[confKey.storagePool] != "defaultSP" {
		t.Error("Unexpected storage pool value")
	}
	if data[confKey.volumeName] != "test-vol" {
		t.Error("Unexpected volume name value")
	}
	if data[confKey.fsType] != "ext4" {
		t.Error("Unexpected fstype value")
	}
	if data[confKey.secretRef] != "test-secret" {
		t.Error("Unexpected secret ref value")
	}
	if data[confKey.sslEnabled] != "false" {
		t.Error("Unexpected sslEnabled value")
	}
	if data[confKey.readOnly] != "false" {
		t.Error("Unexpected readOnly value: ", data[confKey.readOnly])
	}
}

func TestUtilValidateConfigs(t *testing.T) {
	data := map[string]string{
		confKey.secretRef: "sio-secret",
		confKey.system:    "sio",
	}
	if err := validateConfigs(data); err != gatewayNotProvidedErr {
		t.Error("Expecting error for missing gateway, but did not get it")
	}
}

func TestUtilApplyConfigDefaults(t *testing.T) {
	data := map[string]string{
		confKey.system:     "sio",
		confKey.gateway:    "http://sio/",
		confKey.volumeName: "sio-vol",
		confKey.secretRef:  "test-secret",
	}
	applyConfigDefaults(data)

	if data[confKey.gateway] != "http://sio/" {
		t.Error("Unexpected gateway value")
	}
	if data[confKey.system] != "sio" {
		t.Error("Unexpected system value")
	}
	if data[confKey.protectionDomain] != "default" {
		t.Error("Unexpected protection domain value")
	}
	if data[confKey.storagePool] != "default" {
		t.Error("Unexpected storage pool value")
	}
	if data[confKey.volumeName] != "sio-vol" {
		t.Error("Unexpected volume name value")
	}
	if data[confKey.fsType] != "xfs" {
		t.Error("Unexpected fstype value")
	}
	if data[confKey.storageMode] != "ThinProvisioned" {
		t.Error("Unexpected storage mode value")
	}
	if data[confKey.secretRef] != "test-secret" {
		t.Error("Unexpected secret ref value")
	}
	if data[confKey.sslEnabled] != "false" {
		t.Error("Unexpected sslEnabled value")
	}
	if data[confKey.readOnly] != "false" {
		t.Error("Unexpected readOnly value: ", data[confKey.readOnly])
	}
}

func TestUtilDefaultString(t *testing.T) {
	if defaultString("", "foo") != "foo" {
		t.Error("Unexpected value for default value")
	}
}

func TestUtilSaveConfig(t *testing.T) {
	tmpDir, err := utiltesting.MkTmpdir("scaleio-test")
	if err != nil {
		t.Fatalf("can't make a temp dir: %v", err)
	}
	defer os.RemoveAll(tmpDir)

	config := path.Join(tmpDir, testConfigFile)
	data := map[string]string{
		confKey.gateway:    "https://test-gateway/",
		confKey.secretRef:  "sio-secret",
		confKey.sslEnabled: "false",
	}
	if err := saveConfig(config, data); err != nil {
		t.Fatal("failed while saving data", err)
	}
	file, err := os.Open(config)
	if err != nil {
		t.Fatal("failed to open conf file: ", file)
	}
	defer file.Close()
	dataRcvd := map[string]string{}
	if err := gob.NewDecoder(file).Decode(&dataRcvd); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(data, dataRcvd) {
		t.Error("we got problem, config data not the same")
	}
}

func TestUtilAttachSecret(t *testing.T) {
	plugMgr, tmpDir := newPluginMgr(t)
	defer os.RemoveAll(tmpDir)

	plug, err := plugMgr.FindPluginByName(sioPluginName)
	if err != nil {
		t.Errorf("Can't find the plugin %v", sioPluginName)
	}
	sioPlug, ok := plug.(*sioPlugin)
	if !ok {
		t.Errorf("Cannot assert plugin to be type sioPlugin")
	}

	data := make(map[string]string)
	for k, v := range config {
		data[k] = v
	}
	if err := attachSecret(sioPlug, "default", data); err != nil {
		t.Errorf("failed to setupConfigData %v", err)
	}
	if data[confKey.username] == "" {
		t.Errorf("failed to merge secret")
	}
}

func TestUtilLoadConfig(t *testing.T) {
	tmpDir, err := utiltesting.MkTmpdir("scaleio-test")
	if err != nil {
		t.Fatalf("can't make a temp dir: %v", err)
	}
	defer os.RemoveAll(tmpDir)

	configFile := path.Join(tmpDir, sioConfigFileName)

	if err := saveConfig(configFile, config); err != nil {
		t.Fatal("failed while saving data", err)
	}

	dataRcvd, err := loadConfig(configFile)
	if dataRcvd[confKey.gateway] != config[confKey.gateway] ||
		dataRcvd[confKey.system] != config[confKey.system] {
		t.Fatal("loaded config data not matching saved config data")
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Matt Jibson <matt.jibson@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package goon

import (
	"appengine/datastore"
	"bytes"
	"encoding/gob"
	"fmt"
)

// Entity contains data to fetch and store datastore entities.
// The internal fields are designed to be used in a readonly fashion.
type Entity struct {
	Key      *datastore.Key
	Src      interface{}

	NotFound bool
}

func (e *Entity) memkey() string {
	return memkey(e.Key)
}

type partialEntity struct {
	Src      interface{}
	NotFound bool
}

func (e *Entity) gob() ([]byte, error) {
	var buf bytes.Buffer
	enc := gob.NewEncoder(&buf)
	gob.Register(e.Src)
	p := &partialEntity{
		Src:      e.Src,
		NotFound: e.NotFound,
	}
	err := enc.Encode(p)
	if err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

func (e *Entity) String() string {
	return fmt.Sprintf("%v: %v", e.Key, e.Src)
}

// NewEntity returns a new Entity from key and src.
func NewEntity(key *datastore.Key, src interface{}) *Entity {
	e := &Entity{
		Src: src,
	}
	e.setKey(key)
	return e
}

func (e *Entity) setKey(key *datastore.Key) {
	e.Key = key
}

// NewEntity returns a new Entity from src with an incomplete key.
func (g *Goon) NewEntity(parent *datastore.Key, src interface{}) (*Entity, error) {
	k, err := structKind(src)
	if err != nil {
		return nil, err
	}
	return NewEntity(datastore.NewIncompleteKey(g.context, k, parent), src), nil
}

// NewEntityById returns a new Entity from src with a key made from given IDs.
func (g *Goon) NewEntityById(stringID string, intID int64, parent *datastore.Key, src interface{}) (*Entity, error) {
	k, err := structKind(src)
	if err != nil {
		return nil, err
	}
	return NewEntity(datastore.NewKey(g.context, k, stringID, intID, parent), src), nil
}

// KeyEntity returns a new Entity from key and src.
// Refer to appengine/datastore.NewKey regarding key specification.
func (g *Goon) KeyEntity(src interface{}, stringID string, intID int64, parent *datastore.Key) (*Entity, error) {
	k, e := structKind(src)
	if e != nil {
		return nil, e
	}
	return NewEntity(datastore.NewKey(g.context, k, stringID, intID, parent), src), nil
}
<commit_msg>go fmt<commit_after>/*
 * Copyright (c) 2012 Matt Jibson <matt.jibson@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package goon

import (
	"appengine/datastore"
	"bytes"
	"encoding/gob"
	"fmt"
)

// Entity contains data to fetch and store datastore entities.
// The internal fields are designed to be used in a readonly fashion.
type Entity struct {
	Key *datastore.Key
	Src interface{}

	NotFound bool
}

func (e *Entity) memkey() string {
	return memkey(e.Key)
}

type partialEntity struct {
	Src      interface{}
	NotFound bool
}

func (e *Entity) gob() ([]byte, error) {
	var buf bytes.Buffer
	enc := gob.NewEncoder(&buf)
	gob.Register(e.Src)
	p := &partialEntity{
		Src:      e.Src,
		NotFound: e.NotFound,
	}
	err := enc.Encode(p)
	if err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

func (e *Entity) String() string {
	return fmt.Sprintf("%v: %v", e.Key, e.Src)
}

// NewEntity returns a new Entity from key and src.
func NewEntity(key *datastore.Key, src interface{}) *Entity {
	e := &Entity{
		Src: src,
	}
	e.setKey(key)
	return e
}

func (e *Entity) setKey(key *datastore.Key) {
	e.Key = key
}

// NewEntity returns a new Entity from src with an incomplete key.
func (g *Goon) NewEntity(parent *datastore.Key, src interface{}) (*Entity, error) {
	k, err := structKind(src)
	if err != nil {
		return nil, err
	}
	return NewEntity(datastore.NewIncompleteKey(g.context, k, parent), src), nil
}

// NewEntityById returns a new Entity from src with a key made from given IDs.
func (g *Goon) NewEntityById(stringID string, intID int64, parent *datastore.Key, src interface{}) (*Entity, error) {
	k, err := structKind(src)
	if err != nil {
		return nil, err
	}
	return NewEntity(datastore.NewKey(g.context, k, stringID, intID, parent), src), nil
}

// KeyEntity returns a new Entity from key and src.
// Refer to appengine/datastore.NewKey regarding key specification.
func (g *Goon) KeyEntity(src interface{}, stringID string, intID int64, parent *datastore.Key) (*Entity, error) {
	k, e := structKind(src)
	if e != nil {
		return nil, e
	}
	return NewEntity(datastore.NewKey(g.context, k, stringID, intID, parent), src), nil
}
<|endoftext|>


<commit_before>package epochs

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"math"
	"math/big"
	"time"
)

const SecondsPerDay = 24 * 60 * 60
const NanosecondsPerDay = SecondsPerDay * 1e9

// epoch2time gets a Unix time of the given x after dividing by q and
// adding s.
func epoch2time(x, q, s *big.Int) time.Time {
	z := new(big.Int)
	m := new(big.Int)
	z.DivMod(x, q, m)
	z.Add(z, s)
	r := m.Mul(m, big.NewInt(1e9)).Div(m, q)
	return time.Unix(z.Int64(), r.Int64()).UTC()
}

// time2epoch reverses epoch2time.
func time2epoch(t time.Time, m, s *big.Int) int64 {
	bf := new(big.Float).SetInt(big.NewInt(t.UnixNano()))
	bf.Quo(bf, big.NewFloat(1e9))
	bf.Sub(bf, new(big.Float).SetInt(s))
	bf.Mul(bf, new(big.Float).SetInt(m))

	r, acc := bf.Int64()
	if acc != big.Exact {
		fmt.Println(acc)
	}

	return r
}

// Chrome time is the number of microseconds since 1601-01-01, which
// is 11,644,473,600 seconds before the Unix epoch.
func Chrome(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e6),
		big.NewInt(-11644473600),
	)
}
func ToChrome(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e6),
		big.NewInt(-11644473600),
	)
}

// Cocoa time is the number of seconds since 2001-01-01, which
// is 978,307,200 seconds after the Unix epoch.
func Cocoa(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1),
		big.NewInt(978307200),
	)
}
func ToCocoa(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1),
		big.NewInt(978307200),
	)
}

// GoogleCalendar seems to count 32-day months from the day before the
// Unix epoch. @noppers worked out how to do this.
func GoogleCalendar(num int64) time.Time {

	n := int(num)

	totalDays := n / SecondsPerDay
	seconds := n % SecondsPerDay

	// A "Google month" has 32 days!
	months := totalDays / 32
	days := totalDays % 32

	// The "Google epoch" is apparently off by a day.
	t := time.Unix(-SecondsPerDay, 0).UTC()

	// Add the days first...
	u := t.AddDate(0, 0, days)

	// ...then the months...
	v := u.AddDate(0, months, 0)

	// ...then the seconds.
	w := v.Add(time.Duration(seconds * 1e9))

	return w
}
func ToGoogleCalendar(t time.Time) int64 {
	y := t.Year() - 1970
	m := int(t.Month()) - 1
	r := ((((y*12+m)*32+t.Day())*24+t.Hour())*60+t.Minute())*60 + t.Second()
	return int64(r)
}

// ICQ time is the number of days since 1899-12-30, which is
// 2,209,161,600 seconds before the Unix epoch. Days can have a
// fractional part.
func ICQ(days float64) time.Time {

	t := time.Unix(-2209161600, 0).UTC()

	intdays := int(days)

	// Want the fractional part of the day in nanoseconds.
	fracday := int64((days - float64(intdays)) * NanosecondsPerDay)

	return t.AddDate(0, 0, intdays).Add(time.Duration(fracday))
}
func ToICQ(t time.Time) float64 {
	t2 := time.Unix(-2209161600, 0)
	return float64(t.Sub(t2).Nanoseconds()) / float64(NanosecondsPerDay)
}

// Java time is the number of milliseconds since the Unix epoch.
func Java(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1000),
		big.NewInt(0),
	)
}
func ToJava(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1000),
		big.NewInt(0),
	)
}

// Mozilla time (e.g., formhistory.sqlite) is the number of
// microseconds since the Unix epoch.
func Mozilla(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e6),
		big.NewInt(0),
	)
}
func ToMozilla(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e6),
		big.NewInt(0),
	)
}

// OLE time is the number of days since 1899-12-30, which is
// 2,209,161,600 seconds before the Unix epoch. Days can have a
// fractional part and is given as a string of hex characters
// representing an IEEE 8-byte floating-point number.
func OLE(days string) time.Time {
	var d [8]byte
	var f float64

	n, err := fmt.Sscanf(
		days,
		"%02x%02x%02x%02x%02x%02x%02x%02x",
		&d[0], &d[1], &d[2], &d[3], &d[4], &d[5], &d[6], &d[7],
	)
	if err != nil {
		fmt.Println("fmt.Sscanf failed:", err)
	}
	if n != 8 {
		fmt.Println("fmt.Sscanf did not scan 8 items:", n)
	}

	buf := bytes.NewReader(d[:])
	if err := binary.Read(buf, binary.LittleEndian, &f); err != nil {
		fmt.Println("binary.Read failed:", err)
	}

	return ICQ(f)
}
func ToOLE(t time.Time) string {
	icq := ToICQ(t)
	buf := new(bytes.Buffer)
	err := binary.Write(buf, binary.LittleEndian, math.Float64bits(icq))
	if err != nil {
		fmt.Println("binary.Write failed:", err)
	}
	return fmt.Sprintf("%016x", buf.Bytes())
}

// Symbian time is the number of microseconds since the year 0, which
// is 62,167,219,200 seconds before the Unix epoch.
func Symbian(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e6),
		big.NewInt(-62167219200),
	)
}
func ToSymbian(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e6),
		big.NewInt(-62167219200),
	)
}

// Unix time is the number of seconds since 1970-01-01.
func Unix(num int64) time.Time {
	return time.Unix(num, 0).UTC()
}
func ToUnix(t time.Time) int64 {
	return t.Unix()
}

// UUID version 1 time (RFC 4122) is the number of hectonanoseconds
// (100 ns) since 1582-10-15, which is 12,219,292,800 seconds before
// the Unix epoch.
func UUIDv1(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e7),
		big.NewInt(-12219292800),
	)
}
func ToUUIDv1(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e7),
		big.NewInt(-12219292800),
	)
}

// Windows date time (e.g., .NET) is the number of hectonanoseconds
// (100 ns) since 0001-01-01, which is 62,135,596,800 seconds before
// the Unix epoch.
func WindowsDate(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e7),
		big.NewInt(-62135596800),
	)
}
func ToWindowsDate(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e7),
		big.NewInt(-62135596800),
	)
}

// Windows file time (e.g., NTFS) is the number of hectonanoseconds
// (100 ns) since 1601-01-01, which is 11,644,473,600 seconds before
// the Unix epoch.
func WindowsFile(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e7),
		big.NewInt(-11644473600),
	)
}
func ToWindowsFile(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e7),
		big.NewInt(-11644473600),
	)
}
<commit_msg>make go vet happier<commit_after>package epochs

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"math"
	"math/big"
	"time"
)

const secondsPerDay = 24 * 60 * 60
const nanosecondsPerDay = secondsPerDay * 1e9

// epoch2time gets a Unix time of the given x after dividing by q and
// adding s.
func epoch2time(x, q, s *big.Int) time.Time {
	z := new(big.Int)
	m := new(big.Int)
	z.DivMod(x, q, m)
	z.Add(z, s)
	r := m.Mul(m, big.NewInt(1e9)).Div(m, q)
	return time.Unix(z.Int64(), r.Int64()).UTC()
}

// time2epoch reverses epoch2time.
func time2epoch(t time.Time, m, s *big.Int) int64 {
	bf := new(big.Float).SetInt(big.NewInt(t.UnixNano()))
	bf.Quo(bf, big.NewFloat(1e9))
	bf.Sub(bf, new(big.Float).SetInt(s))
	bf.Mul(bf, new(big.Float).SetInt(m))

	r, acc := bf.Int64()
	if acc != big.Exact {
		fmt.Println(acc)
	}

	return r
}

// Chrome time is the number of microseconds since 1601-01-01, which
// is 11,644,473,600 seconds before the Unix epoch.
func Chrome(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e6),
		big.NewInt(-11644473600),
	)
}

// ToChrome returns the Chrome time for the given time.Time.
func ToChrome(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e6),
		big.NewInt(-11644473600),
	)
}

// Cocoa time is the number of seconds since 2001-01-01, which
// is 978,307,200 seconds after the Unix epoch.
func Cocoa(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1),
		big.NewInt(978307200),
	)
}

// ToCocoa returns the Cocoa time for the given time.Time.
func ToCocoa(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1),
		big.NewInt(978307200),
	)
}

// GoogleCalendar seems to count 32-day months from the day before the
// Unix epoch. @noppers worked out how to do this.
func GoogleCalendar(num int64) time.Time {

	n := int(num)

	totalDays := n / secondsPerDay
	seconds := n % secondsPerDay

	// A "Google month" has 32 days!
	months := totalDays / 32
	days := totalDays % 32

	// The "Google epoch" is apparently off by a day.
	t := time.Unix(-secondsPerDay, 0).UTC()

	// Add the days first...
	u := t.AddDate(0, 0, days)

	// ...then the months...
	v := u.AddDate(0, months, 0)

	// ...then the seconds.
	w := v.Add(time.Duration(seconds * 1e9))

	return w
}

// ToGoogleCalendar returns the GoogleCalendar time for the given time.Time.
func ToGoogleCalendar(t time.Time) int64 {
	y := t.Year() - 1970
	m := int(t.Month()) - 1
	r := ((((y*12+m)*32+t.Day())*24+t.Hour())*60+t.Minute())*60 + t.Second()
	return int64(r)
}

// ICQ time is the number of days since 1899-12-30, which is
// 2,209,161,600 seconds before the Unix epoch. Days can have a
// fractional part.
func ICQ(days float64) time.Time {

	t := time.Unix(-2209161600, 0).UTC()

	intdays := int(days)

	// Want the fractional part of the day in nanoseconds.
	fracday := int64((days - float64(intdays)) * nanosecondsPerDay)

	return t.AddDate(0, 0, intdays).Add(time.Duration(fracday))
}

// ToICQ returns the ICQ time for the given time.Time.
func ToICQ(t time.Time) float64 {
	t2 := time.Unix(-2209161600, 0)
	return float64(t.Sub(t2).Nanoseconds()) / float64(nanosecondsPerDay)
}

// Java time is the number of milliseconds since the Unix epoch.
func Java(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1000),
		big.NewInt(0),
	)
}

// ToJava returns the Java time for the given time.Time.
func ToJava(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1000),
		big.NewInt(0),
	)
}

// Mozilla time (e.g., formhistory.sqlite) is the number of
// microseconds since the Unix epoch.
func Mozilla(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e6),
		big.NewInt(0),
	)
}

// ToMozilla returns the Mozilla time for the given time.Time.
func ToMozilla(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e6),
		big.NewInt(0),
	)
}

// OLE time is the number of days since 1899-12-30, which is
// 2,209,161,600 seconds before the Unix epoch. Days can have a
// fractional part and is given as a string of hex characters
// representing an IEEE 8-byte floating-point number.
func OLE(days string) time.Time {
	var d [8]byte
	var f float64

	n, err := fmt.Sscanf(
		days,
		"%02x%02x%02x%02x%02x%02x%02x%02x",
		&d[0], &d[1], &d[2], &d[3], &d[4], &d[5], &d[6], &d[7],
	)
	if err != nil {
		fmt.Println("fmt.Sscanf failed:", err)
	}
	if n != 8 {
		fmt.Println("fmt.Sscanf did not scan 8 items:", n)
	}

	buf := bytes.NewReader(d[:])
	if err := binary.Read(buf, binary.LittleEndian, &f); err != nil {
		fmt.Println("binary.Read failed:", err)
	}

	return ICQ(f)
}

// ToOLE returns the OLE time for the given time.Time.
func ToOLE(t time.Time) string {
	icq := ToICQ(t)
	buf := new(bytes.Buffer)
	err := binary.Write(buf, binary.LittleEndian, math.Float64bits(icq))
	if err != nil {
		fmt.Println("binary.Write failed:", err)
	}
	return fmt.Sprintf("%016x", buf.Bytes())
}

// Symbian time is the number of microseconds since the year 0, which
// is 62,167,219,200 seconds before the Unix epoch.
func Symbian(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e6),
		big.NewInt(-62167219200),
	)
}

// ToSymbian returns the Symbian time for the given time.Time.
func ToSymbian(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e6),
		big.NewInt(-62167219200),
	)
}

// Unix time is the number of seconds since 1970-01-01.
func Unix(num int64) time.Time {
	return time.Unix(num, 0).UTC()
}

// ToUnix returns the Unix time for the given time.Time.
func ToUnix(t time.Time) int64 {
	return t.Unix()
}

// UUID version 1 time (RFC 4122) is the number of hectonanoseconds
// (100 ns) since 1582-10-15, which is 12,219,292,800 seconds before
// the Unix epoch.
func UUIDv1(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e7),
		big.NewInt(-12219292800),
	)
}

// ToUUIDv1 returns the UUIDv1 time for the given time.Time.
func ToUUIDv1(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e7),
		big.NewInt(-12219292800),
	)
}

// Windows date time (e.g., .NET) is the number of hectonanoseconds
// (100 ns) since 0001-01-01, which is 62,135,596,800 seconds before
// the Unix epoch.
func WindowsDate(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e7),
		big.NewInt(-62135596800),
	)
}

// ToWindowsDate returns the WindowsDate time for the given time.Time.
func ToWindowsDate(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e7),
		big.NewInt(-62135596800),
	)
}

// Windows file time (e.g., NTFS) is the number of hectonanoseconds
// (100 ns) since 1601-01-01, which is 11,644,473,600 seconds before
// the Unix epoch.
func WindowsFile(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e7),
		big.NewInt(-11644473600),
	)
}

// ToWindowsFile returns the WindowsFile time for the given time.Time.
func ToWindowsFile(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e7),
		big.NewInt(-11644473600),
	)
}
<|endoftext|>


<commit_before>package llog

import (
	"context"

	"github.com/levenlabs/golib/errctx"
)

type kvKey int

// ErrWithKV embeds the merging of a set of KVs into an error, returning a new
// error instance. If the error already has a KV embedded in it then the
// returned error will have the merging of them all.
func ErrWithKV(err error, kvs ...KV) error {
	if err == nil {
		return nil
	}
	kv := Merge(kvs...)
	existingKV := errctx.Get(err, kvKey(0))
	if existingKV != nil {
		kv = Merge(existingKV.(KV), kv)
	}
	return errctx.Set(err, kvKey(0), kv)
}

// ErrKV returns a copy of the KV embedded in the error by ErrWithKV. Returns
// empty KV if no KV was previously embedded. Will automatically set the "err"
// field on the returned KV as well.
func ErrKV(err error) KV {
	var kv KV
	if kvi := errctx.Get(err, kvKey(0)); kvi == nil {
		return KV{"err": err.Error()}
	}
	return kvi.(KV).Set("err", err.Error())
}

// CtxWithKV embeds a KV into a Context, returning a new Context instance. If
// the Context already has a KV embedded in it then the returned error will have
// the merging of the two.
func CtxWithKV(ctx context.Context, kvs ...KV) context.Context {
	kv := Merge(kvs...)
	existingKV := ctx.Value(kvKey(0))
	if existingKV != nil {
		kv = Merge(existingKV.(KV), kv)
	}
	return context.WithValue(ctx, kvKey(0), kv)
}

// CtxKV returns a copy of the KV embedded in the Context by CtxWithKV
func CtxKV(ctx context.Context) KV {
	kv := ctx.Value(kvKey(0))
	if kv == nil {
		return KV{}
	}
	return kv.(KV)
}
<commit_msg>small fix in errctx<commit_after>package llog

import (
	"context"

	"github.com/levenlabs/golib/errctx"
)

type kvKey int

// ErrWithKV embeds the merging of a set of KVs into an error, returning a new
// error instance. If the error already has a KV embedded in it then the
// returned error will have the merging of them all.
func ErrWithKV(err error, kvs ...KV) error {
	if err == nil {
		return nil
	}
	kv := Merge(kvs...)
	existingKV := errctx.Get(err, kvKey(0))
	if existingKV != nil {
		kv = Merge(existingKV.(KV), kv)
	}
	return errctx.Set(err, kvKey(0), kv)
}

// ErrKV returns a copy of the KV embedded in the error by ErrWithKV. Returns
// empty KV if no KV was previously embedded. Will automatically set the "err"
// field on the returned KV as well.
func ErrKV(err error) KV {
	kvi := errctx.Get(err, kvKey(0))
	if kvi == nil {
		return KV{"err": err.Error()}
	}
	return kvi.(KV).Set("err", err.Error())
}

// CtxWithKV embeds a KV into a Context, returning a new Context instance. If
// the Context already has a KV embedded in it then the returned error will have
// the merging of the two.
func CtxWithKV(ctx context.Context, kvs ...KV) context.Context {
	kv := Merge(kvs...)
	existingKV := ctx.Value(kvKey(0))
	if existingKV != nil {
		kv = Merge(existingKV.(KV), kv)
	}
	return context.WithValue(ctx, kvKey(0), kv)
}

// CtxKV returns a copy of the KV embedded in the Context by CtxWithKV
func CtxKV(ctx context.Context) KV {
	kv := ctx.Value(kvKey(0))
	if kv == nil {
		return KV{}
	}
	return kv.(KV)
}
<|endoftext|>


<commit_before>package bugsnag

import (
	"fmt"
	"os"
	"reflect"
	"runtime"
	"strings"
)

type stacktraceFrame struct {
	File       string `json:"file"`
	LineNumber uint   `json:"lineNumber"`
	Method     string `json:"method"`
}

type bugsnagException struct {
	ErrorClass string            `json:"errorClass"`
	Message    string            `json:"message"`
	StackTrace []stacktraceFrame `json:"stacktrace"`
}

type bugsnagEvent struct {
	UserId       string             `json:"userId,omitempty"`
	AppVersion   string             `json:"appVersion,omitempty"`
	OsVersion    string             `json:"osVersion,omitempty"`
	ReleaseStage string             `json:"releaseStage"`
	Context      string             `json:"context,omitempty"`
	GroupingHash string             `json:"groupingHash,omitempty"`
	Exceptions   []bugsnagException `json:"exceptions"`
}

type bugsnagNotification struct {
	ApiKey       string         `json:"apiKey"`
	NotifierInfo *notifierInfo  `json:"notifier"`
	Events       []bugsnagEvent `json:"events"`
}

func getErrorTypeName(err interface{}) string {
	errorType := reflect.TypeOf(err)
	if errorType.Kind() == reflect.Ptr {
		errorType = errorType.Elem()
	}
	return fmt.Sprintf("%s:%s", errorType.PkgPath(), errorType.Name())
}

func getStackFrames(skipFrames, maxFrames int) []stacktraceFrame {
	if skipFrames < 0 {
		skipFrames = 0
	}

	callers := make([]uintptr, maxFrames)
	depth := runtime.Callers(skipFrames+2, callers)
	output := make([]stacktraceFrame, depth)

	written := 0

	for i := 0; i < depth; i++ {
		pc := callers[i]
		fn := runtime.FuncForPC(pc)
		if fn == nil {
			break
		} else if fn.Name() == "runtime.panic" {
			continue
		}

		filename, line := fn.FileLine(pc)

		filename = simplifyFilePath(filename)

		output[written] = stacktraceFrame{File: filename, LineNumber: uint(line), Method: fn.Name()}
		written++
	}

	return output[:written]
}

var goroot string
var sourcePaths []string

func init() {
	goroot = runtime.GOROOT() + "/src/pkg/"
	sourcePaths = strings.Split(os.Getenv("GOPATH"), ":")
}

func simplifyFilePath(path string) string {
	pathLen := len(path)
	if strings.HasPrefix(path, goroot) && pathLen > len(goroot) {
		return path[len(goroot):]
	}
	for _, tmpPath := range sourcePaths {
		var check string
		if len(tmpPath) > 1 && tmpPath[0] == '/' {
			check = tmpPath[1:]
		} else {
			check = tmpPath
		}
		if strings.HasPrefix(path, check) && pathLen > len(check) {
			var src, pkg string
			src = path + "src/"
			pkg = path + "pkg/"
			if strings.HasPrefix(path, src) && pathLen > len(src) {
				return path[len(src):]
			} else if strings.HasPrefix(path, pkg) && pathLen > len(pkg) {
				return path[len(pkg):]
			} else {
				return path[len(check):]
			}
		}
	}
	if pathLen > 1 && path[0] == '/' {
		path = path[1:]
	}
	return path
}
<commit_msg>Cleaned up some usages of path separator literals inside errors.go<commit_after>package bugsnag

import (
	"fmt"
	"os"
	"reflect"
	"runtime"
	"strings"
)

type stacktraceFrame struct {
	File       string `json:"file"`
	LineNumber uint   `json:"lineNumber"`
	Method     string `json:"method"`
}

type bugsnagException struct {
	ErrorClass string            `json:"errorClass"`
	Message    string            `json:"message"`
	StackTrace []stacktraceFrame `json:"stacktrace"`
}

type bugsnagEvent struct {
	UserId       string             `json:"userId,omitempty"`
	AppVersion   string             `json:"appVersion,omitempty"`
	OsVersion    string             `json:"osVersion,omitempty"`
	ReleaseStage string             `json:"releaseStage"`
	Context      string             `json:"context,omitempty"`
	GroupingHash string             `json:"groupingHash,omitempty"`
	Exceptions   []bugsnagException `json:"exceptions"`
}

type bugsnagNotification struct {
	ApiKey       string         `json:"apiKey"`
	NotifierInfo *notifierInfo  `json:"notifier"`
	Events       []bugsnagEvent `json:"events"`
}

func getErrorTypeName(err interface{}) string {
	errorType := reflect.TypeOf(err)
	if errorType.Kind() == reflect.Ptr {
		errorType = errorType.Elem()
	}
	return fmt.Sprintf("%s:%s", errorType.PkgPath(), errorType.Name())
}

func getStackFrames(skipFrames, maxFrames int) []stacktraceFrame {
	if skipFrames < 0 {
		skipFrames = 0
	}

	callers := make([]uintptr, maxFrames)
	depth := runtime.Callers(skipFrames+2, callers)
	output := make([]stacktraceFrame, depth)

	written := 0

	for i := 0; i < depth; i++ {
		pc := callers[i]
		fn := runtime.FuncForPC(pc)
		if fn == nil {
			break
		} else if fn.Name() == "runtime.panic" {
			continue
		}

		filename, line := fn.FileLine(pc)

		filename = simplifyFilePath(filename)

		output[written] = stacktraceFrame{File: filename, LineNumber: uint(line), Method: fn.Name()}
		written++
	}

	return output[:written]
}

var goroot string
var sourcePaths []string

func init() {
	goroot = runtime.GOROOT() + os.PathSeparator + "src" + os.PathSeparator + "pkg" + os.PathSeparator
	sourcePaths = strings.Split(os.Getenv("GOPATH"), ":")
}

func simplifyFilePath(path string) string {
	pathLen := len(path)
	if strings.HasPrefix(path, goroot) && pathLen > len(goroot) {
		return path[len(goroot):]
	}
	for _, tmpPath := range sourcePaths {
		var check string
		if len(tmpPath) > 1 && os.IsPathSeparator(tmpPath[0]) {
			check = tmpPath[1:]
		} else {
			check = tmpPath
		}
		if strings.HasPrefix(path, check) && pathLen > len(check) {
			var src, pkg string
			src = path + "src" + os.PathSeparator
			pkg = path + "pkg" + os.PathSeparator
			if strings.HasPrefix(path, src) && pathLen > len(src) {
				return path[len(src):]
			} else if strings.HasPrefix(path, pkg) && pathLen > len(pkg) {
				return path[len(pkg):]
			} else {
				return path[len(check):]
			}
		}
	}
	if pathLen > 1 && os.IsPathSeparator(path[0]) {
		path = path[1:]
	}
	return path
}
<|endoftext|>


<commit_before>/*
   Copyright The containerd Authors.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package fifo

import (
	"errors"
)

var (
	ErrClosed       = errors.New("fifo closed")
	ErrCtrlClosed   = errors.New("control of closed fifo")
	ErrRdFrmWRONLY  = errors.New("reading from write-only fifo")
	ErrReadClosed   = errors.New("reading from a closed fifo")
	ErrWrToRDONLY   = errors.New("writing to read-only fifo")
	ErrWriteClosed  = errors.New("writing to a closed fifo")
)
<commit_msg>fix gofmt<commit_after>/*
   Copyright The containerd Authors.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package fifo

import (
	"errors"
)

var (
	ErrClosed      = errors.New("fifo closed")
	ErrCtrlClosed  = errors.New("control of closed fifo")
	ErrRdFrmWRONLY = errors.New("reading from write-only fifo")
	ErrReadClosed  = errors.New("reading from a closed fifo")
	ErrWrToRDONLY  = errors.New("writing to read-only fifo")
	ErrWriteClosed = errors.New("writing to a closed fifo")
)
<|endoftext|>


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

package fuse

import (
	"syscall"

	"github.com/jacobsa/bazilfuse"
)

const (
	// Errors corresponding to kernel error numbers. These may be treated
	// specially by fuseops.Op.Respond methods.
	EEXIST    = bazilfuse.EEXIST
	EINVAL    = bazilfuse.Errno(syscall.EINVAL)
	EIO       = bazilfuse.EIO
	ENOENT    = bazilfuse.ENOENT
	ENOSYS    = bazilfuse.ENOSYS
	ENOTEMPTY = bazilfuse.Errno(syscall.ENOTEMPTY)
)
<commit_msg>Added ENOTDIR.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package fuse

import (
	"syscall"

	"github.com/jacobsa/bazilfuse"
)

const (
	// Errors corresponding to kernel error numbers. These may be treated
	// specially by fuseops.Op.Respond methods.
	EEXIST    = bazilfuse.EEXIST
	EINVAL    = bazilfuse.Errno(syscall.EINVAL)
	EIO       = bazilfuse.EIO
	ENOENT    = bazilfuse.ENOENT
	ENOSYS    = bazilfuse.ENOSYS
	ENOTDIR   = bazilfuse.Errno(syscall.ENOTDIR)
	ENOTEMPTY = bazilfuse.Errno(syscall.ENOTEMPTY)
)
<|endoftext|>


<commit_before>package sandwich

import (
	"errors"
	"fmt"
	"net/http"
)

// Error is an error implementation that provides the ability to specify three
// things to the sandwich error handler:
//   * The HTTP status code that should be used in the response.
//   * The client-facing message that should be sent.  Typically this is a
//     sanitized error message, such as "Internal Server Error".
//   * Internal debugging detail including a log message and the underlying
//     error that should be included in the server logs.
// Note that Cause may be nil.
type Error struct {
	Code      int
	ClientMsg string
	LogMsg    string
	Cause     error
}

func (e Error) Error() string {
	return fmt.Sprintf("[%d] %s: %v", e.Code, e.LogMsg, e.Cause)
}

// Done is a sentinel error value that can be used to interrupt the middleware
// chain without triggering the default error handling.  HandleError will not
// attempt to write any status code or client message, nor will it add the error
// to the log.
var Done = errors.New("<done>")

func handleErrorCommon(w http.ResponseWriter, r *http.Request, l *LogEntry, err error) Error {
	e, ok := err.(Error)
	if !ok {
		e = Error{LogMsg: "Failure", Cause: err}
	}
	if e.Code == 0 {
		e.Code = 500
	}

	if e.ClientMsg == "" {
		e.ClientMsg = http.StatusText(e.Code)
	}
	if e.LogMsg != "" {
		msg := fmt.Sprintf("(%d) %s", e.Code, e.LogMsg)
		if e.Cause != nil {
			msg += ": " + e.Cause.Error()
		}
		l.Error = errors.New(msg)
	}
	return e
}

// HandleError is the default error handler included in sandwich.TheUsual.
// If the error is a sandwich.Error, it responds with the specified status code
// and client message.  Otherwise, it responds with a 500.  In both cases, the
// underlying error is added to the request log.
//
// If the error is sandwich.Done, HandleError does nothing.
func HandleError(w http.ResponseWriter, r *http.Request, l *LogEntry, err error) {
	if err == Done {
		return
	}
	e := handleErrorCommon(w, r, l, err)
	http.Error(w, e.ClientMsg, e.Code)
}

// HandleErrorJson is identical to HandleError except that it responds to the
// client as JSON instead of plain text.  Again, detailed error info is added
// to the request log.
//
// If the error is sandwich.Done, HandleErrorJson does nothing.
func HandleErrorJson(w http.ResponseWriter, r *http.Request, l *LogEntry, err error) {
	if err == Done {
		return
	}
	e := handleErrorCommon(w, r, l, err)
	w.Header().Set("Content-Type", "application/json")
	http.Error(w, fmt.Sprintf(`{"error":%q}`, e.ClientMsg), e.Code)
}
<commit_msg>Improve error handling: expose ToError and (sandwich.Error).LogIfMsg<commit_after>package sandwich

import (
	"errors"
	"fmt"
	"net/http"
)

// Error is an error implementation that provides the ability to specify three
// things to the sandwich error handler:
//   * The HTTP status code that should be used in the response.
//   * The client-facing message that should be sent.  Typically this is a
//     sanitized error message, such as "Internal Server Error".
//   * Internal debugging detail including a log message and the underlying
//     error that should be included in the server logs.
// Note that Cause may be nil.
type Error struct {
	Code      int
	ClientMsg string
	LogMsg    string
	Cause     error
}

func (e Error) Error() string {
	msg := fmt.Sprintf("(%d) %s", e.Code, e.LogMsg)
	if e.Cause != nil {
		msg += ": " + e.Cause.Error()
	}
	return msg
}

// LogIfMsg will set the Error field on the LogEntry if the Error's LogMsg
// field has something.
func (e Error) LogIfMsg(l *LogEntry) {
	if e.LogMsg != "" {
		l.Error = e
	}
}

// Done is a sentinel error value that can be used to interrupt the middleware
// chain without triggering the default error handling.  HandleError will not
// attempt to write any status code or client message, nor will it add the error
// to the log.
var Done = errors.New("<done>")

// ToError will convert a generic non-nil error to an explicit sandwich.Error
// type.  If err is already a sandwich.Error, it will be returned.  Otherwise, a
// generic 500 Error (internal server error) will be initialized and returned.
// Note that if err is nil, it will still return a generic 500 Error.
func ToError(err error) Error {
	e, ok := err.(Error)
	if !ok {
		e = Error{LogMsg: "Failure", Cause: err}
	}
	if e.Code == 0 {
		e.Code = 500
	}
	if e.ClientMsg == "" {
		e.ClientMsg = http.StatusText(e.Code)
	}
	return e
}

// HandleError is the default error handler included in sandwich.TheUsual.
// If the error is a sandwich.Error, it responds with the specified status code
// and client message.  Otherwise, it responds with a 500.  In both cases, the
// underlying error is added to the request log.
//
// If the error is sandwich.Done, HandleError does nothing.
func HandleError(w http.ResponseWriter, r *http.Request, l *LogEntry, err error) {
	if err == Done {
		return
	}
	e := ToError(err)
	e.LogIfMsg(l)
	http.Error(w, e.ClientMsg, e.Code)
}

// HandleErrorJson is identical to HandleError except that it responds to the
// client as JSON instead of plain text.  Again, detailed error info is added
// to the request log.
//
// If the error is sandwich.Done, HandleErrorJson does nothing.
func HandleErrorJson(w http.ResponseWriter, r *http.Request, l *LogEntry, err error) {
	if err == Done {
		return
	}
	e := ToError(err)
	e.LogIfMsg(l)
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(e.Code)
	fmt.Fprintf(w, `{"error":%q}`, e.ClientMsg)
}
<|endoftext|>


<commit_before>package stm

import (
	"fmt"
	"net/url"
	"strings"
	"time"

	"github.com/beevik/etree"
	"github.com/imdario/mergo"
)

// Change to News type def
func SetBuilderElementValue(elm *etree.Element, data map[string]interface{}, basekey string) bool {
	key := basekey
	ts, tk := spaceDecompose(elm.Tag)
	_, sk := spaceDecompose(elm.Space)

	if elm.Tag != "" && ts != "" && tk != "" {
		key = fmt.Sprintf("%s:%s", elm.Space, basekey)
	} else if sk != "" {
		key = fmt.Sprintf("%s:%s", sk, basekey)
	}

	if values, ok := data[basekey]; ok {
		switch value := values.(type) {
		case nil:
		default:
			child := elm.CreateElement(key)
			child.SetText(fmt.Sprint(value))
		case int:
			child := elm.CreateElement(key)
			child.SetText(fmt.Sprint(value))
		case string:
			child := elm.CreateElement(key)
			child.SetText(value)
		case float64, float32:
			child := elm.CreateElement(key)
			child.SetText(fmt.Sprint(value))
		case time.Time:
			child := elm.CreateElement(key)
			child.SetText(value.Format(time.RFC3339))
		case bool:
			_ = elm.CreateElement(fmt.Sprintf("%s:%s", key, key))
		case []string:
			for _, v := range value {
				child := elm.CreateElement(key)
				child.SetText(v)
			}
		case interface{}:
			var childkey string
			if sk == "" {
				childkey = fmt.Sprintf("%s:%s", key, key)
			} else {
				childkey = fmt.Sprint(key)
			}

			switch value := values.(type) {
			case []URL:
				for _, v := range value {
					child := elm.CreateElement(childkey)
					for ck, _ := range v {
						SetBuilderElementValue(child, v, ck)
					}
				}
			case URL:
				child := elm.CreateElement(childkey)
				for ck, _ := range value {
					SetBuilderElementValue(child, value, ck)
				}
			}
		}

		return true
	}
	return false
}

// TODO: Slow function: It wants to change fast function
func MergeMap(src, dst map[string]interface{}) map[string]interface{} {
	mergo.MapWithOverwrite(&dst, src)
	return dst
}

func ToLowerString(befores []string) (afters []string) {
	for _, name := range befores {
		afters = append(afters, strings.ToLower(name))
	}
	return afters
}

// TODO: Too slowly
func URLJoin(src string, joins ...string) string {
	var u *url.URL
	lastnum := len(joins)
	base, _ := url.Parse(src)

	for i, j := range joins {
		if !strings.HasSuffix(j, "/") && lastnum > (i+1) {
			j = j + "/"
		}

		u, _ = url.Parse(j)
		base = base.ResolveReference(u)
	}

	return base.String()
}

func spaceDecompose(str string) (space, key string) {
	colon := strings.IndexByte(str, ':')
	if colon == -1 {
		return "", str
	}
	return str[:colon], str[colon+1:]
}
<commit_msg>added comment<commit_after>package stm

import (
	"fmt"
	"net/url"
	"strings"
	"time"

	"github.com/beevik/etree"
	"github.com/imdario/mergo"
)

// XXX: It changes to News type def
// It will change to struct from map if the future's author is feeling a bothersome in this function.
func SetBuilderElementValue(elm *etree.Element, data map[string]interface{}, basekey string) bool {
	key := basekey
	ts, tk := spaceDecompose(elm.Tag)
	_, sk := spaceDecompose(elm.Space)

	if elm.Tag != "" && ts != "" && tk != "" {
		key = fmt.Sprintf("%s:%s", elm.Space, basekey)
	} else if sk != "" {
		key = fmt.Sprintf("%s:%s", sk, basekey)
	}

	if values, ok := data[basekey]; ok {
		switch value := values.(type) {
		case nil:
		default:
			child := elm.CreateElement(key)
			child.SetText(fmt.Sprint(value))
		case int:
			child := elm.CreateElement(key)
			child.SetText(fmt.Sprint(value))
		case string:
			child := elm.CreateElement(key)
			child.SetText(value)
		case float64, float32:
			child := elm.CreateElement(key)
			child.SetText(fmt.Sprint(value))
		case time.Time:
			child := elm.CreateElement(key)
			child.SetText(value.Format(time.RFC3339))
		case bool:
			_ = elm.CreateElement(fmt.Sprintf("%s:%s", key, key))
		case []int:
			for _, v := range value {
				child := elm.CreateElement(key)
				child.SetText(fmt.Sprint(v))
			}
		case []string:
			for _, v := range value {
				child := elm.CreateElement(key)
				child.SetText(v)
			}
		case interface{}:
			var childkey string
			if sk == "" {
				childkey = fmt.Sprintf("%s:%s", key, key)
			} else {
				childkey = fmt.Sprint(key)
			}

			switch value := values.(type) {
			case []URL:
				for _, v := range value {
					child := elm.CreateElement(childkey)
					for ck, _ := range v {
						SetBuilderElementValue(child, v, ck)
					}
				}
			case URL:
				child := elm.CreateElement(childkey)
				for ck, _ := range value {
					SetBuilderElementValue(child, value, ck)
				}
			}
		}

		return true
	}
	return false
}

// TODO: Slow function: It wants to change fast function
func MergeMap(src, dst map[string]interface{}) map[string]interface{} {
	mergo.MapWithOverwrite(&dst, src)
	return dst
}

func ToLowerString(befores []string) (afters []string) {
	for _, name := range befores {
		afters = append(afters, strings.ToLower(name))
	}
	return afters
}

// TODO: Too slowly
func URLJoin(src string, joins ...string) string {
	var u *url.URL
	lastnum := len(joins)
	base, _ := url.Parse(src)

	for i, j := range joins {
		if !strings.HasSuffix(j, "/") && lastnum > (i+1) {
			j = j + "/"
		}

		u, _ = url.Parse(j)
		base = base.ResolveReference(u)
	}

	return base.String()
}

func spaceDecompose(str string) (space, key string) {
	colon := strings.IndexByte(str, ':')
	if colon == -1 {
		return "", str
	}
	return str[:colon], str[colon+1:]
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
)

var (
	action   = flag.String("action", "evaluate", "What should I do?")
	language = flag.String("language", "", "Language to evaluate")
)

func usage() {
	fmt.Fprintf(os.Stderr, "Usage: evalgd [flags]\n")
	fmt.Fprintf(os.Stderr, "Defaults are:\n")
	flag.PrintDefaults()
	os.Exit(2)
}

func main() {
	flag.Usage = usage
	flag.Parse()

	if flag.NFlag() == 0 {
		flag.Usage()
	}

	fmt.Println("Requesting evaluation...")
	code, _ := ioutil.ReadAll(os.Stdin)
	e := Evaluation{
		Language: *language,
		Code:     string(code),
	}

	result, statusCode := evaluate(e)

	if statusCode != 200 {
		fmt.Printf("[\x1b[31;1mError\x1b[0m] HTTP Code %d\n", statusCode)
	} else {
		fmt.Println(string(result))
	}
}

type Evaluation struct {
	Language string `json:"language"`
	Code     string `json:"code"`
}

func evaluate(e Evaluation) (string, int) {
	jsonQuery, _ := json.Marshal(e)
	query := bytes.NewBuffer(jsonQuery)
	resp, _ := http.Post(
		"http://eval.gd/jsontest",
		"application/json",
		query)
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	return string(body), resp.StatusCode
}
<commit_msg>Add ability to specify server and add better debug messages.<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
)

var (
	action   = flag.String("action", "evaluate", "What should I do?")
	language = flag.String("language", "", "Language to evaluate.")
	debug    = flag.Bool("debug", false, "Print debugging output?")
	server   = flag.String("server", "http://eval.gd", "API server to evaluate against.")
)

func usage() {
	fmt.Fprintf(os.Stderr, "Usage: evalgd [flags]\n")
	fmt.Fprintf(os.Stderr, "Defaults are:\n")
	flag.PrintDefaults()
	os.Exit(2)
}

func printDebug(message string)  {
	if *debug {
		fmt.Printf("[\x1b[33;1mDEBUG\x1b[0m] %s\n", message)
	}
}

func main() {
	flag.Usage = usage
	flag.Parse()

	if flag.NFlag() == 0 {
		flag.Usage()
	}

	printDebug("Requesting evaluation...")
	code, _ := ioutil.ReadAll(os.Stdin)
	e := Evaluation{
		Language: *language,
		Code:     string(code),
	}

	result, statusCode := evaluate(e)

	if statusCode != 200 {
		fmt.Printf("[\x1b[31;1mError\x1b[0m] HTTP Code %d\n", statusCode)
	} else {
		fmt.Println(string(result))
	}
}

type Evaluation struct {
	Language string `json:"language"`
	Code     string `json:"code"`
}

func evaluate(e Evaluation) (string, int) {
	jsonQuery, _ := json.Marshal(e)
	query := bytes.NewBuffer(jsonQuery)
	resp, _ := http.Post(
		fmt.Sprintf("%s/jsontest", *server),
		"application/json",
		query)
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	return string(body), resp.StatusCode
}
<|endoftext|>