<commit_before>package minify // import "github.com/tdewolff/minify"

import (
	"io"
	"io/ioutil"
	"math"
	"math/rand"
	"strconv"
	"testing"

	"github.com/stretchr/testify/assert"
)

func assertDataURI(t *testing.T, m Minifier, s, e string) {
	assert.Equal(t, e, string(DataURI(m, []byte(s))), "data URIs must match")
}

func assertNumber(t *testing.T, x, e string) {
	assert.Equal(t, e, string(Number([]byte(x))), "numbers must match in "+x)
}

func assertLenInt(t *testing.T, x int64) {
	e := 1
	if x != 0 {
		e = int(math.Log10(math.Abs(float64(x)))) + 1
	}
	assert.Equal(t, e, lenInt64(int64(x)), "number lengths must match for "+strconv.FormatInt(x, 10))
}

////////////////////////////////////////////////////////////////

func TestContentType(t *testing.T) {
	assert.Equal(t, "text/html", string(ContentType([]byte("text/html"))))
	assert.Equal(t, "text/html;charset=utf-8", string(ContentType([]byte("text/html; charset=UTF-8"))))
	assert.Equal(t, "text/html;charset=utf-8;param=\" ; \"", string(ContentType([]byte("text/html; charset=UTF-8 ; param = \" ; \""))))
	assert.Equal(t, "text/html,text/css", string(ContentType([]byte("text/html, text/css"))))
}

func TestDataURI(t *testing.T) {
	m := New()
	m.AddFunc("text/x", func(m Minifier, mediatype string, w io.Writer, r io.Reader) error {
		b, _ := ioutil.ReadAll(r)
		assert.Equal(t, "<?x?>", string(b))
		w.Write(b)
		return nil
	})
	assertDataURI(t, m, "data:text/x,<?x?>", "data:text/x,%3C%3Fx%3F%3E")
	assertDataURI(t, m, "data:,text", "data:,text")
	assertDataURI(t, m, "data:;base64,dGV4dA==", "data:,text")
	assertDataURI(t, m, "data:text/svg+xml;base64,PT09PT09", "data:text/svg+xml;base64,PT09PT09")
	assertDataURI(t, m, "data:text/xml;version=2.0,content", "data:text/xml;version=2.0,content")
	assertDataURI(t, m, "data:text/xml; version = 2.0,content", "data:text/xml;version=2.0,content")
	assertDataURI(t, m, "data:,=====", "data:,%3D%3D%3D%3D%3D")
	assertDataURI(t, m, "data:,======", "data:;base64,PT09PT09")
}

func TestNumber(t *testing.T) {
	assertNumber(t, "0", "0")
	assertNumber(t, ".0", "0")
	assertNumber(t, "1.0", "1")
	assertNumber(t, "0.1", ".1")
	assertNumber(t, "+1", "1")
	assertNumber(t, "-1", "-1")
	assertNumber(t, "-0.1", "-.1")
	assertNumber(t, "100", "100")
	assertNumber(t, "1000", "1e3")
	assertNumber(t, "0.001", ".001")
	assertNumber(t, "0.0001", "1e-4")
	assertNumber(t, "100e1", "1e3")
	assertNumber(t, "1.1e+1", "11")
	assertNumber(t, "0.252", ".252")
	assertNumber(t, "1.252", "1.252")
	assertNumber(t, "-1.252", "-1.252")
	assertNumber(t, "0.075", ".075")
	assertNumber(t, "789012345678901234567890123456789e9234567890123456789", "789012345678901234567890123456789e9234567890123456789")
	assertNumber(t, ".000100009", "100009e-9")
	assertNumber(t, ".0001000009", ".0001000009")
	assertNumber(t, ".0001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009", ".0001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009")
	//assertNumber(t, "96px", "1in")
}

func TestLenInt(t *testing.T) {
	assertLenInt(t, 0)
	assertLenInt(t, 1)
	assertLenInt(t, 10)
	assertLenInt(t, 99)
}

////////////////

var num []int64

func TestMain(t *testing.T) {
	for j := 0; j < 1000; j++ {
		num = append(num, rand.Int63n(1000))
	}
}

func BenchmarkLenIntLog(b *testing.B) {
	n := 0
	for i := 0; i < b.N; i++ {
		for j := 0; j < 1000; j++ {
			n += int(math.Log10(math.Abs(float64(num[j])))) + 1
		}
	}
}

func BenchmarkLenIntSwitch(b *testing.B) {
	n := 0
	for i := 0; i < b.N; i++ {
		for j := 0; j < 1000; j++ {
			n += lenInt64(num[j])
		}
	}
}
<commit_msg>Fuzz bug test<commit_after>package minify // import "github.com/tdewolff/minify"

import (
	"io"
	"io/ioutil"
	"math"
	"math/rand"
	"strconv"
	"testing"

	"github.com/stretchr/testify/assert"
)

func assertDataURI(t *testing.T, m Minifier, s, e string) {
	assert.Equal(t, e, string(DataURI(m, []byte(s))), "data URIs must match")
}

func assertNumber(t *testing.T, x, e string) {
	assert.Equal(t, e, string(Number([]byte(x))), "numbers must match in "+x)
}

func assertLenInt(t *testing.T, x int64) {
	e := 1
	if x != 0 {
		e = int(math.Log10(math.Abs(float64(x)))) + 1
	}
	assert.Equal(t, e, lenInt64(int64(x)), "number lengths must match for "+strconv.FormatInt(x, 10))
}

////////////////////////////////////////////////////////////////

func TestContentType(t *testing.T) {
	assert.Equal(t, "text/html", string(ContentType([]byte("text/html"))))
	assert.Equal(t, "text/html;charset=utf-8", string(ContentType([]byte("text/html; charset=UTF-8"))))
	assert.Equal(t, "text/html;charset=utf-8;param=\" ; \"", string(ContentType([]byte("text/html; charset=UTF-8 ; param = \" ; \""))))
	assert.Equal(t, "text/html,text/css", string(ContentType([]byte("text/html, text/css"))))
}

func TestDataURI(t *testing.T) {
	m := New()
	m.AddFunc("text/x", func(m Minifier, mediatype string, w io.Writer, r io.Reader) error {
		b, _ := ioutil.ReadAll(r)
		assert.Equal(t, "<?x?>", string(b))
		w.Write(b)
		return nil
	})
	assertDataURI(t, m, "data:text/x,<?x?>", "data:text/x,%3C%3Fx%3F%3E")
	assertDataURI(t, m, "data:,text", "data:,text")
	assertDataURI(t, m, "data:;base64,dGV4dA==", "data:,text")
	assertDataURI(t, m, "data:text/svg+xml;base64,PT09PT09", "data:text/svg+xml;base64,PT09PT09")
	assertDataURI(t, m, "data:text/xml;version=2.0,content", "data:text/xml;version=2.0,content")
	assertDataURI(t, m, "data:text/xml; version = 2.0,content", "data:text/xml;version=2.0,content")
	assertDataURI(t, m, "data:,=====", "data:,%3D%3D%3D%3D%3D")
	assertDataURI(t, m, "data:,======", "data:;base64,PT09PT09")
}

func TestNumber(t *testing.T) {
	assertNumber(t, "0", "0")
	assertNumber(t, ".0", "0")
	assertNumber(t, "1.0", "1")
	assertNumber(t, "0.1", ".1")
	assertNumber(t, "+1", "1")
	assertNumber(t, "-1", "-1")
	assertNumber(t, "-0.1", "-.1")
	assertNumber(t, "100", "100")
	assertNumber(t, "1000", "1e3")
	assertNumber(t, "0.001", ".001")
	assertNumber(t, "0.0001", "1e-4")
	assertNumber(t, "100e1", "1e3")
	assertNumber(t, "1.1e+1", "11")
	assertNumber(t, "0.252", ".252")
	assertNumber(t, "1.252", "1.252")
	assertNumber(t, "-1.252", "-1.252")
	assertNumber(t, "0.075", ".075")
	assertNumber(t, "789012345678901234567890123456789e9234567890123456789", "789012345678901234567890123456789e9234567890123456789")
	assertNumber(t, ".000100009", "100009e-9")
	assertNumber(t, ".0001000009", ".0001000009")
	assertNumber(t, ".0001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009", ".0001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009")
	assertNumber(t, "E\x1f", "E\x1f") // fuzz
	//assertNumber(t, "96px", "1in")
}

func TestLenInt(t *testing.T) {
	assertLenInt(t, 0)
	assertLenInt(t, 1)
	assertLenInt(t, 10)
	assertLenInt(t, 99)
}

////////////////

var num []int64

func TestMain(t *testing.T) {
	for j := 0; j < 1000; j++ {
		num = append(num, rand.Int63n(1000))
	}
}

func BenchmarkLenIntLog(b *testing.B) {
	n := 0
	for i := 0; i < b.N; i++ {
		for j := 0; j < 1000; j++ {
			n += int(math.Log10(math.Abs(float64(num[j])))) + 1
		}
	}
}

func BenchmarkLenIntSwitch(b *testing.B) {
	n := 0
	for i := 0; i < b.N; i++ {
		for j := 0; j < 1000; j++ {
			n += lenInt64(num[j])
		}
	}
}
<|endoftext|>


<commit_before>package atlas

import (
	"bytes"
	"fmt"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"io/ioutil"
	"net/http"
	"testing"
)

func TestGetVersion(t *testing.T) {
	ver := GetVersion()
	assert.EqualValues(t, ourVersion, ver, "should be equal")
}

func TestGetPageNum(t *testing.T) {
	url := "https://foo.example.com/"

	n := getPageNum(url)
	if n != "" {
		t.Errorf("n=%s should be ''", n)
	}
	url = "https://foo.example.com/?page=42"
	n = getPageNum(url)
	if n != "42" {
		t.Errorf("n=%s should be 42", n)
	}
	url = "https://foo.example.com/?country=fr&page=43"
	n = getPageNum(url)
	if n != "43" {
		t.Errorf("n=%s should be 43", n)
	}
	url = "https://foo.example.com/?country=fr&page=666&bar=1"
	n = getPageNum(url)
	if n != "666" {
		t.Errorf("n=%s should be 666", n)
	}

	url = ""
	n = getPageNum(url)
	if n != "" {
		t.Errorf("n=%s should be ''", n)
	}
}

func TestClienthandleAPIResponsese(t *testing.T) {
	var (
		r http.Response
		b bytes.Buffer
	)

	client, err := NewClient()
	err = client.handleAPIResponsese(nil)
	assert.Error(t, err, "should be in error")

	r = http.Response{StatusCode: 0}
	err = client.handleAPIResponsese(&r)
	assert.NoError(t, err, "should be no error")

	r = http.Response{StatusCode: 200}
	err = client.handleAPIResponsese(&r)
	assert.NoError(t, err, "should be no error")

	var jsonErr = `error:{status: 501, code: 500, detail: "test"}`

	fmt.Fprintf(&b, "%v", jsonErr)
	r.StatusCode = 300
	r.Body = ioutil.NopCloser(&b)
	err = client.handleAPIResponsese(&r)
	assert.NoError(t, err, "should be in error")

	r.StatusCode = 500
	r.Body = ioutil.NopCloser(&b)
	err = client.handleAPIResponsese(&r)
	assert.Error(t, err, "should be in error")
}

func TestAddQueryParameters(t *testing.T) {
	p := AddQueryParameters("", map[string]string{})
	assert.Equal(t, "", p)
}

func TestAddQueryParameters_1(t *testing.T) {
	p := AddQueryParameters("", map[string]string{"": ""})
	assert.Equal(t, "?=", p)
}

func TestAddQueryParameters_2(t *testing.T) {
	p := AddQueryParameters("foo", map[string]string{"bar": "baz"})
	assert.Equal(t, "foo?bar=baz", p)
}

func TestClient_AddAPIKey(t *testing.T) {
	c, err := NewClient(Config{APIKey:"foo"})
	require.NoError(t, err)
	assert.NotNil(t, c)
	assert.NotEmpty(t, c)

	opts := map[string]string{}

	new := c.addAPIKey(opts)
	assert.NotEmpty(t, c.config.APIKey)
	assert.Equal(t, 1, len(new))
	assert.EqualValues(t, map[string]string{"key": "foo"}, new)
}
<commit_msg>Tests for prepareRequest().<commit_after>package atlas

import (
	"bytes"
	"fmt"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"io/ioutil"
	"net/http"
	"net/url"
	"testing"
)

const testURL  = "http://localhost:10000"

func TestGetVersion(t *testing.T) {
	ver := GetVersion()
	assert.EqualValues(t, ourVersion, ver, "should be equal")
}

func TestGetPageNum(t *testing.T) {
	url := "https://foo.example.com/"

	n := getPageNum(url)
	if n != "" {
		t.Errorf("n=%s should be ''", n)
	}
	url = "https://foo.example.com/?page=42"
	n = getPageNum(url)
	if n != "42" {
		t.Errorf("n=%s should be 42", n)
	}
	url = "https://foo.example.com/?country=fr&page=43"
	n = getPageNum(url)
	if n != "43" {
		t.Errorf("n=%s should be 43", n)
	}
	url = "https://foo.example.com/?country=fr&page=666&bar=1"
	n = getPageNum(url)
	if n != "666" {
		t.Errorf("n=%s should be 666", n)
	}

	url = ""
	n = getPageNum(url)
	if n != "" {
		t.Errorf("n=%s should be ''", n)
	}
}

func TestClienthandleAPIResponsese(t *testing.T) {
	var (
		r http.Response
		b bytes.Buffer
	)

	client, err := NewClient()
	err = client.handleAPIResponsese(nil)
	assert.Error(t, err, "should be in error")

	r = http.Response{StatusCode: 0}
	err = client.handleAPIResponsese(&r)
	assert.NoError(t, err, "should be no error")

	r = http.Response{StatusCode: 200}
	err = client.handleAPIResponsese(&r)
	assert.NoError(t, err, "should be no error")

	var jsonErr = `error:{status: 501, code: 500, detail: "test"}`

	fmt.Fprintf(&b, "%v", jsonErr)
	r.StatusCode = 300
	r.Body = ioutil.NopCloser(&b)
	err = client.handleAPIResponsese(&r)
	assert.NoError(t, err, "should be in error")

	r.StatusCode = 500
	r.Body = ioutil.NopCloser(&b)
	err = client.handleAPIResponsese(&r)
	assert.Error(t, err, "should be in error")
}

func TestAddQueryParameters(t *testing.T) {
	p := AddQueryParameters("", map[string]string{})
	assert.Equal(t, "", p)
}

func TestAddQueryParameters_1(t *testing.T) {
	p := AddQueryParameters("", map[string]string{"": ""})
	assert.Equal(t, "?=", p)
}

func TestAddQueryParameters_2(t *testing.T) {
	p := AddQueryParameters("foo", map[string]string{"bar": "baz"})
	assert.Equal(t, "foo?bar=baz", p)
}

func TestClient_AddAPIKey(t *testing.T) {
	c, err := NewClient(Config{APIKey:"foo"})
	require.NoError(t, err)
	assert.NotNil(t, c)
	assert.NotEmpty(t, c)

	opts := map[string]string{}

	new := c.addAPIKey(opts)
	assert.NotEmpty(t, c.config.APIKey)
	assert.Equal(t, 1, len(new))
	assert.EqualValues(t, map[string]string{"key": "foo"}, new)
}

func TestPrepareRequest(t *testing.T) {
	c, err := NewClient(Config{endpoint: testURL})
	require.NoError(t, err)

	opts := map[string]string{}
	req := c.prepareRequest("GET", "foo", opts)

	assert.NotNil(t, req)
	assert.IsType(t, (*http.Request)(nil), req)

	res, _ := url.Parse(testURL + "/foo")
	assert.Equal(t, "GET", req.Method)
	assert.EqualValues(t, res, req.URL)
}

func TestPrepareRequest_2(t *testing.T) {
	c, err := NewClient()
	require.NoError(t, err)

	opts := map[string]string{}
	req := c.prepareRequest("GET", "foo", opts)

	assert.NotNil(t, req)
	assert.IsType(t, (*http.Request)(nil), req)

	res, _ := url.Parse(apiEndpoint + "/foo")
	assert.Equal(t, "GET", req.Method)
	assert.EqualValues(t, res, req.URL)
}
<|endoftext|>


<commit_before>package win

import (
	"image"
	"syscall"
	"unsafe"

	"github.com/AllenDang/w32"
	"github.com/kirillDanshin/go-wde"
)

const WDEM_UI_THREAD = w32.WM_APP

type EventData struct {
	lastX, lastY int
	button       wde.Button
	noX          int
	trackMouse   bool
}

func (this *EventData) InitEventData() {
	this.noX = 1<<31 - 1
	this.noX++
	this.lastX = this.noX
}

func buttonForDetail(button uint32) wde.Button {
	switch button {
	case w32.WM_LBUTTONDOWN, w32.WM_LBUTTONUP:
		return wde.LeftButton
	case w32.WM_RBUTTONDOWN, w32.WM_RBUTTONUP:
		return wde.RightButton
	case w32.WM_MBUTTONDOWN, w32.WM_MBUTTONUP:
		return wde.MiddleButton
	}
	return 0
}

func WndProc(hwnd w32.HWND, msg uint32, wparam, lparam uintptr) uintptr {
	wnd := GetMsgHandler(hwnd)
	if wnd == nil {
		return uintptr(w32.DefWindowProc(hwnd, msg, wparam, lparam))
	}

	var rc uintptr
	switch msg {
	case w32.WM_ACTIVATE:
		if wparam&0xffff != 0 {
			/* This window has just been granted focus, so flag our internal
			** key state as stale. We can't simply refresh our state because
			** win32's GetKeyboardState isn't always accurate at this point
			** in the event stream. */
			wnd.keysStale = true
		}
		rc = w32.DefWindowProc(hwnd, msg, wparam, lparam)

	case w32.WM_SHOWWINDOW:
		w32.SetFocus(hwnd)
		wnd.restoreCursor()

	case w32.WM_LBUTTONDOWN, w32.WM_RBUTTONDOWN, w32.WM_MBUTTONDOWN:
		wnd.button = wnd.button | buttonForDetail(msg)
		var bpe wde.MouseDownEvent
		bpe.Which = buttonForDetail(msg)
		bpe.Where.X = int(lparam) & 0xFFFF
		bpe.Where.Y = int(lparam>>16) & 0xFFFF
		wnd.lastX = bpe.Where.X
		wnd.lastY = bpe.Where.Y
		wnd.events <- bpe

	case w32.WM_LBUTTONUP, w32.WM_RBUTTONUP, w32.WM_MBUTTONUP:
		wnd.button = wnd.button & ^buttonForDetail(msg)
		var bpe wde.MouseUpEvent
		bpe.Which = buttonForDetail(msg)
		bpe.Where.X = int(lparam) & 0xFFFF
		bpe.Where.Y = int(lparam>>16) & 0xFFFF
		wnd.lastX = bpe.Where.X
		wnd.lastY = bpe.Where.Y
		wnd.events <- bpe

	case w32.WM_MOUSEWHEEL:
		var me wde.MouseEvent
		screenX := int(lparam) & 0xFFFF
		screenY := int(lparam>>16) & 0xFFFF
		me.Where.X, me.Where.Y, _ = w32.ScreenToClient(wnd.hwnd, screenX, screenY)
		button := wde.WheelDownButton
		delta := int16((wparam >> 16) & 0xFFFF)
		if delta > 0 {
			button = wde.WheelUpButton
		}
		wnd.lastX = me.Where.X
		wnd.lastX = me.Where.Y
		wnd.events <- wde.MouseDownEvent{me, button}
		wnd.events <- wde.MouseUpEvent{me, button}

	case w32.WM_MOUSEMOVE:
		var mme wde.MouseMovedEvent
		mme.Where.X = int(lparam) & 0xFFFF
		mme.Where.Y = int(lparam>>16) & 0xFFFF
		if wnd.lastX != wnd.noX {
			mme.From.X = int(wnd.lastX)
			mme.From.Y = int(wnd.lastY)
		} else {
			mme.From.X = mme.Where.X
			mme.From.Y = mme.Where.Y
		}
		wnd.lastX = mme.Where.X
		wnd.lastY = mme.Where.Y

		if !wnd.trackMouse {
			var tme w32.TRACKMOUSEEVENT
			tme.CbSize = uint32(unsafe.Sizeof(tme))
			tme.DwFlags = w32.TME_LEAVE
			tme.HwndTrack = hwnd
			tme.DwHoverTime = w32.HOVER_DEFAULT
			w32.TrackMouseEvent(&tme)
			wnd.trackMouse = true
			wnd.restoreCursor()
			wnd.events <- wde.MouseEnteredEvent(mme)
		} else {
			if wnd.button == 0 {
				wnd.events <- mme
			} else {
				var mde wde.MouseDraggedEvent
				mde.MouseMovedEvent = mme
				mde.Which = wnd.button
				wnd.events <- mde
			}
		}

	case w32.WM_MOUSELEAVE:
		wnd.trackMouse = false

		var wee wde.MouseExitedEvent
		// TODO: get real position
		wee.Where.Y = wnd.lastX
		wee.Where.X = wnd.lastY
		wnd.events <- wee

	case w32.WM_SYSKEYDOWN, w32.WM_KEYDOWN:
		translatable := w32.MapVirtualKeyEx(uint(wparam), w32.MAPVK_VK_TO_CHAR, w32.HKL(0))
		wnd.keyDown = keyFromVirtualKeyCode(wparam)
		wnd.keysDown[wnd.keyDown] = true
		wnd.checkKeyState()
		wnd.events <- wde.KeyDownEvent{wnd.keyDown}
		if translatable == 0 {
			kpe := wde.KeyTypedEvent{
				wde.KeyEvent{wnd.keyDown},
				"",
				wnd.constructChord(),
			}
			wnd.events <- kpe
		}
	case w32.WM_SYSCHAR, w32.WM_CHAR:
		glyph := syscall.UTF16ToString([]uint16{uint16(wparam)})
		kpe := wde.KeyTypedEvent{
			wde.KeyEvent{wnd.keyDown},
			glyph,
			wnd.constructChord(),
		}
		wnd.events <- kpe
	case w32.WM_SYSKEYUP, w32.WM_KEYUP:
		keyUp := keyFromVirtualKeyCode(wparam)
		delete(wnd.keysDown, keyUp)
		wnd.checkKeyState()
		wnd.events <- wde.KeyUpEvent{
			keyUp,
		}

	case w32.WM_SIZE:
		width := int(lparam) & 0xFFFF
		height := int(lparam>>16) & 0xFFFF
		wnd.buffer = NewDIB(image.Rect(0, 0, width, height))
		wnd.events <- wde.ResizeEvent{width, height}
		rc = w32.DefWindowProc(hwnd, msg, wparam, lparam)

	case w32.WM_PAINT:
		wnd.Repaint()
		rc = w32.DefWindowProc(hwnd, msg, wparam, lparam)

	case WDEM_UI_THREAD:
		f := <-wnd.uiTasks
		f()

	case w32.WM_CLOSE:
		wnd.events <- wde.CloseEvent{}

	case w32.WM_DESTROY:
		w32.PostQuitMessage(0)

	default:
		rc = w32.DefWindowProc(hwnd, msg, wparam, lparam)
	}

	return rc
}
<commit_msg>use named import for govet<commit_after>package win

import (
	"image"
	"syscall"
	"unsafe"

	"github.com/AllenDang/w32"
	wde "github.com/kirillDanshin/go-wde"
)

const WDEM_UI_THREAD = w32.WM_APP

type EventData struct {
	lastX, lastY int
	button       wde.Button
	noX          int
	trackMouse   bool
}

func (this *EventData) InitEventData() {
	this.noX = 1<<31 - 1
	this.noX++
	this.lastX = this.noX
}

func buttonForDetail(button uint32) wde.Button {
	switch button {
	case w32.WM_LBUTTONDOWN, w32.WM_LBUTTONUP:
		return wde.LeftButton
	case w32.WM_RBUTTONDOWN, w32.WM_RBUTTONUP:
		return wde.RightButton
	case w32.WM_MBUTTONDOWN, w32.WM_MBUTTONUP:
		return wde.MiddleButton
	}
	return 0
}

func WndProc(hwnd w32.HWND, msg uint32, wparam, lparam uintptr) uintptr {
	wnd := GetMsgHandler(hwnd)
	if wnd == nil {
		return uintptr(w32.DefWindowProc(hwnd, msg, wparam, lparam))
	}

	var rc uintptr
	switch msg {
	case w32.WM_ACTIVATE:
		if wparam&0xffff != 0 {
			/* This window has just been granted focus, so flag our internal
			** key state as stale. We can't simply refresh our state because
			** win32's GetKeyboardState isn't always accurate at this point
			** in the event stream. */
			wnd.keysStale = true
		}
		rc = w32.DefWindowProc(hwnd, msg, wparam, lparam)

	case w32.WM_SHOWWINDOW:
		w32.SetFocus(hwnd)
		wnd.restoreCursor()

	case w32.WM_LBUTTONDOWN, w32.WM_RBUTTONDOWN, w32.WM_MBUTTONDOWN:
		wnd.button = wnd.button | buttonForDetail(msg)
		var bpe wde.MouseDownEvent
		bpe.Which = buttonForDetail(msg)
		bpe.Where.X = int(lparam) & 0xFFFF
		bpe.Where.Y = int(lparam>>16) & 0xFFFF
		wnd.lastX = bpe.Where.X
		wnd.lastY = bpe.Where.Y
		wnd.events <- bpe

	case w32.WM_LBUTTONUP, w32.WM_RBUTTONUP, w32.WM_MBUTTONUP:
		wnd.button = wnd.button & ^buttonForDetail(msg)
		var bpe wde.MouseUpEvent
		bpe.Which = buttonForDetail(msg)
		bpe.Where.X = int(lparam) & 0xFFFF
		bpe.Where.Y = int(lparam>>16) & 0xFFFF
		wnd.lastX = bpe.Where.X
		wnd.lastY = bpe.Where.Y
		wnd.events <- bpe

	case w32.WM_MOUSEWHEEL:
		var me wde.MouseEvent
		screenX := int(lparam) & 0xFFFF
		screenY := int(lparam>>16) & 0xFFFF
		me.Where.X, me.Where.Y, _ = w32.ScreenToClient(wnd.hwnd, screenX, screenY)
		button := wde.WheelDownButton
		delta := int16((wparam >> 16) & 0xFFFF)
		if delta > 0 {
			button = wde.WheelUpButton
		}
		wnd.lastX = me.Where.X
		wnd.lastX = me.Where.Y
		wnd.events <- wde.MouseDownEvent{me, button}
		wnd.events <- wde.MouseUpEvent{me, button}

	case w32.WM_MOUSEMOVE:
		var mme wde.MouseMovedEvent
		mme.Where.X = int(lparam) & 0xFFFF
		mme.Where.Y = int(lparam>>16) & 0xFFFF
		if wnd.lastX != wnd.noX {
			mme.From.X = int(wnd.lastX)
			mme.From.Y = int(wnd.lastY)
		} else {
			mme.From.X = mme.Where.X
			mme.From.Y = mme.Where.Y
		}
		wnd.lastX = mme.Where.X
		wnd.lastY = mme.Where.Y

		if !wnd.trackMouse {
			var tme w32.TRACKMOUSEEVENT
			tme.CbSize = uint32(unsafe.Sizeof(tme))
			tme.DwFlags = w32.TME_LEAVE
			tme.HwndTrack = hwnd
			tme.DwHoverTime = w32.HOVER_DEFAULT
			w32.TrackMouseEvent(&tme)
			wnd.trackMouse = true
			wnd.restoreCursor()
			wnd.events <- wde.MouseEnteredEvent(mme)
		} else {
			if wnd.button == 0 {
				wnd.events <- mme
			} else {
				var mde wde.MouseDraggedEvent
				mde.MouseMovedEvent = mme
				mde.Which = wnd.button
				wnd.events <- mde
			}
		}

	case w32.WM_MOUSELEAVE:
		wnd.trackMouse = false

		var wee wde.MouseExitedEvent
		// TODO: get real position
		wee.Where.Y = wnd.lastX
		wee.Where.X = wnd.lastY
		wnd.events <- wee

	case w32.WM_SYSKEYDOWN, w32.WM_KEYDOWN:
		translatable := w32.MapVirtualKeyEx(uint(wparam), w32.MAPVK_VK_TO_CHAR, w32.HKL(0))
		wnd.keyDown = keyFromVirtualKeyCode(wparam)
		wnd.keysDown[wnd.keyDown] = true
		wnd.checkKeyState()
		wnd.events <- wde.KeyDownEvent{wnd.keyDown}
		if translatable == 0 {
			kpe := wde.KeyTypedEvent{
				wde.KeyEvent{wnd.keyDown},
				"",
				wnd.constructChord(),
			}
			wnd.events <- kpe
		}
	case w32.WM_SYSCHAR, w32.WM_CHAR:
		glyph := syscall.UTF16ToString([]uint16{uint16(wparam)})
		kpe := wde.KeyTypedEvent{
			wde.KeyEvent{wnd.keyDown},
			glyph,
			wnd.constructChord(),
		}
		wnd.events <- kpe
	case w32.WM_SYSKEYUP, w32.WM_KEYUP:
		keyUp := keyFromVirtualKeyCode(wparam)
		delete(wnd.keysDown, keyUp)
		wnd.checkKeyState()
		wnd.events <- wde.KeyUpEvent{
			keyUp,
		}

	case w32.WM_SIZE:
		width := int(lparam) & 0xFFFF
		height := int(lparam>>16) & 0xFFFF
		wnd.buffer = NewDIB(image.Rect(0, 0, width, height))
		wnd.events <- wde.ResizeEvent{width, height}
		rc = w32.DefWindowProc(hwnd, msg, wparam, lparam)

	case w32.WM_PAINT:
		wnd.Repaint()
		rc = w32.DefWindowProc(hwnd, msg, wparam, lparam)

	case WDEM_UI_THREAD:
		f := <-wnd.uiTasks
		f()

	case w32.WM_CLOSE:
		wnd.events <- wde.CloseEvent{}

	case w32.WM_DESTROY:
		w32.PostQuitMessage(0)

	default:
		rc = w32.DefWindowProc(hwnd, msg, wparam, lparam)
	}

	return rc
}
<|endoftext|>


<commit_before>// Copyright 2015 Hajime Hoshi
//
// 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.

// +build darwin freebsd linux windows
// +build !js
// +build !android
// +build !ios

package ui

import (
	"errors"
	"runtime"
	"sync"
	"time"

	"github.com/go-gl/glfw/v3.2/glfw"
	"github.com/hajimehoshi/ebiten/internal/opengl"
)

type userInterface struct {
	title           string
	window          *glfw.Window
	width           int
	height          int
	scale           float64
	deviceScale     float64
	glfwScale       float64
	fullscreen      bool
	fullscreenScale float64
	funcs           chan func()
	running         bool
	sizeChanged     bool
	origPosX        int
	origPosY        int
	m               sync.Mutex
}

var currentUI *userInterface

func init() {
	if err := initialize(); err != nil {
		panic(err)
	}
}

func initialize() error {
	runtime.LockOSThread()

	if err := glfw.Init(); err != nil {
		return err
	}
	glfw.WindowHint(glfw.Visible, glfw.False)
	glfw.WindowHint(glfw.Resizable, glfw.False)
	glfw.WindowHint(glfw.ContextVersionMajor, 2)
	glfw.WindowHint(glfw.ContextVersionMinor, 1)

	// As start, create an window with temporary size to create OpenGL context thread.
	window, err := glfw.CreateWindow(16, 16, "", nil, nil)
	if err != nil {
		return err
	}
	hideConsoleWindowOnWindows()
	u := &userInterface{
		window:      window,
		funcs:       make(chan func()),
		sizeChanged: true,
		origPosX:    -1,
		origPosY:    -1,
	}
	u.window.MakeContextCurrent()
	glfw.SwapInterval(1)
	currentUI = u
	return nil
}

func RunMainThreadLoop(ch <-chan error) error {
	// TODO: Check this is done on the main thread.
	currentUI.setRunning(true)
	defer func() {
		currentUI.setRunning(false)
	}()
	for {
		select {
		case f := <-currentUI.funcs:
			f()
		case err := <-ch:
			// ch returns a value not only when an error occur but also it is closed.
			return err
		}
	}
}

func (u *userInterface) isRunning() bool {
	u.m.Lock()
	defer u.m.Unlock()
	return u.running
}

func (u *userInterface) setRunning(running bool) {
	u.m.Lock()
	defer u.m.Unlock()
	u.running = running
}

func (u *userInterface) runOnMainThread(f func() error) error {
	if u.funcs == nil {
		// already closed
		return nil
	}
	ch := make(chan struct{})
	var err error
	u.funcs <- func() {
		err = f()
		close(ch)
	}
	<-ch
	return err
}

func SetScreenSize(width, height int) bool {
	u := currentUI
	if !u.isRunning() {
		panic("ui: Run is not called yet")
	}
	r := false
	_ = u.runOnMainThread(func() error {
		r = u.setScreenSize(width, height, u.scale, u.fullscreen)
		return nil
	})
	return r
}

func SetScreenScale(scale float64) bool {
	u := currentUI
	if !u.isRunning() {
		panic("ui: Run is not called yet")
	}
	r := false
	_ = u.runOnMainThread(func() error {
		r = u.setScreenSize(u.width, u.height, scale, u.fullscreen)
		return nil
	})
	return r
}

func SetFullscreen(fullscreen bool) bool {
	u := currentUI
	if !u.isRunning() {
		panic("ui: Run is not called yet")
	}
	r := false
	_ = u.runOnMainThread(func() error {
		r = u.setScreenSize(u.width, u.height, u.scale, fullscreen)
		return nil
	})
	return r
}

func ScreenScale() float64 {
	u := currentUI
	if !u.isRunning() {
		return 0
	}
	s := 0.0
	_ = u.runOnMainThread(func() error {
		s = u.scale
		return nil
	})
	return s
}

func IsFullscreen() bool {
	u := currentUI
	if !u.isRunning() {
		return false
	}
	f := false
	_ = u.runOnMainThread(func() error {
		f = u.fullscreen
		return nil
	})
	return f
}

func SetCursorVisibility(visible bool) {
	// This can be called before Run: change the state asyncly.
	go func() {
		_ = currentUI.runOnMainThread(func() error {
			c := glfw.CursorNormal
			if !visible {
				c = glfw.CursorHidden
			}
			currentUI.window.SetInputMode(glfw.CursorMode, c)
			return nil
		})
	}()
}

func Run(width, height int, scale float64, title string, g GraphicsContext) error {
	u := currentUI
	// GLContext must be created before setting the screen size, which requires
	// swapping buffers.
	opengl.Init(currentUI.runOnMainThread)
	if err := u.runOnMainThread(func() error {
		m := glfw.GetPrimaryMonitor()
		v := m.GetVideoMode()
		if !u.setScreenSize(width, height, scale, false) {
			return errors.New("ui: Fail to set the screen size")
		}
		u.title = title
		u.window.SetTitle(title)
		u.window.Show()

		w, h := u.glfwSize()
		x := (v.Width - w) / 2
		y := (v.Height - h) / 3
		x, y = adjustWindowPosition(x, y)
		u.window.SetPos(x, y)
		return nil
	}); err != nil {
		return err
	}
	return u.loop(g)
}

func (u *userInterface) glfwSize() (int, int) {
	if u.glfwScale == 0 {
		u.glfwScale = glfwScale()
	}
	return int(float64(u.width) * u.scale * u.glfwScale), int(float64(u.height) * u.scale * u.glfwScale)
}

func (u *userInterface) getScale() float64 {
	if !u.fullscreen {
		return u.scale
	}
	if u.fullscreenScale == 0 {
		if u.glfwScale == 0 {
			u.glfwScale = glfwScale()
		}
		m := glfw.GetPrimaryMonitor()
		v := m.GetVideoMode()
		sw := float64(v.Width) / u.glfwScale / float64(u.width)
		sh := float64(v.Height) / u.glfwScale / float64(u.height)
		s := sw
		if s > sh {
			s = sh
		}
		u.fullscreenScale = s
	}
	return u.fullscreenScale
}

func (u *userInterface) actualScreenScale() float64 {
	if u.deviceScale == 0 {
		u.deviceScale = deviceScale()
	}
	return u.getScale() * u.deviceScale
}

func (u *userInterface) pollEvents() {
	glfw.PollEvents()
	if u.glfwScale == 0 {
		u.glfwScale = glfwScale()
	}
	currentInput.update(u.window, u.getScale()*u.glfwScale)
}

func (u *userInterface) update(g GraphicsContext) error {
	shouldClose := false
	_ = u.runOnMainThread(func() error {
		shouldClose = u.window.ShouldClose()
		return nil
	})
	if shouldClose {
		return &RegularTermination{}
	}

	actualScale := 0.0
	_ = u.runOnMainThread(func() error {
		if !u.sizeChanged {
			return nil
		}
		u.sizeChanged = false
		actualScale = u.actualScreenScale()
		return nil
	})
	if 0 < actualScale {
		g.SetSize(u.width, u.height, actualScale)
	}

	_ = u.runOnMainThread(func() error {
		u.pollEvents()
		for u.window.GetAttrib(glfw.Focused) == 0 {
			// Wait for an arbitrary period to avoid busy loop.
			time.Sleep(time.Second / 60)
			u.pollEvents()
			if u.window.ShouldClose() {
				return nil
			}
		}
		return nil
	})
	if err := g.Update(); err != nil {
		return err
	}
	return nil
}

func (u *userInterface) loop(g GraphicsContext) error {
	defer func() {
		_ = u.runOnMainThread(func() error {
			glfw.Terminate()
			return nil
		})
	}()
	for {
		if err := u.update(g); err != nil {
			return err
		}
		// The bound framebuffer must be the default one (0) before swapping buffers.
		if err := opengl.GetContext().BindScreenFramebuffer(); err != nil {
			return err
		}
		_ = u.runOnMainThread(func() error {
			u.swapBuffers()
			return nil
		})
	}
}

func (u *userInterface) swapBuffers() {
	u.window.SwapBuffers()
}

func (u *userInterface) setScreenSize(width, height int, scale float64, fullscreen bool) bool {
	if u.width == width && u.height == height && u.scale == scale && u.fullscreen == fullscreen {
		return false
	}

	origScale := u.scale
	u.scale = scale

	// On Windows, giving a too small width doesn't call a callback (#165).
	// To prevent hanging up, return asap if the width is too small.
	// 252 is an arbitrary number and I guess this is small enough.
	// TODO: The same check should be in ui_js.go
	const minWindowWidth = 252
	if int(float64(width)*u.actualScreenScale()) < minWindowWidth {
		u.scale = origScale
		return false
	}
	if u.width != width || u.height != height {
		u.width = width
		u.height = height
		u.fullscreenScale = 0
	}

	// To make sure the current existing framebuffers are rendered,
	// swap buffers here before SetSize is called.
	u.swapBuffers()

	u.fullscreen = fullscreen

	window := u.window
	m := glfw.GetPrimaryMonitor()
	v := m.GetVideoMode()
	if u.fullscreen {
		if u.origPosX < 0 && u.origPosY < 0 {
			u.origPosX, u.origPosY = window.GetPos()
		}
		window.SetMonitor(m, 0, 0, v.Width, v.Height, v.RefreshRate)
	} else {
		if u.origPosX >= 0 && u.origPosY >= 0 {
			x := u.origPosX
			y := u.origPosY
			window.SetMonitor(nil, x, y, 16, 16, v.RefreshRate)
			u.origPosX = -1
			u.origPosY = -1
		}
		ch := make(chan struct{})
		window.SetFramebufferSizeCallback(func(_ *glfw.Window, width, height int) {
			window.SetFramebufferSizeCallback(nil)
			close(ch)
		})
		w, h := u.glfwSize()
		window.SetSize(w, h)
	event:
		for {
			glfw.PollEvents()
			select {
			case <-ch:
				break event
			default:
			}
		}
		// Window title might lost on macOS after coming back from fullscreen.
		u.window.SetTitle(u.title)
	}
	// TODO: Rename this variable?
	u.sizeChanged = true
	return true
}
<commit_msg>ui: Refactoring<commit_after>// Copyright 2015 Hajime Hoshi
//
// 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.

// +build darwin freebsd linux windows
// +build !js
// +build !android
// +build !ios

package ui

import (
	"errors"
	"runtime"
	"sync"
	"time"

	"github.com/go-gl/glfw/v3.2/glfw"
	"github.com/hajimehoshi/ebiten/internal/opengl"
)

type userInterface struct {
	title           string
	window          *glfw.Window
	width           int
	height          int
	scale           float64
	deviceScale     float64
	glfwScale       float64
	fullscreen      bool
	fullscreenScale float64
	funcs           chan func()
	running         bool
	sizeChanged     bool
	origPosX        int
	origPosY        int
	m               sync.Mutex
}

var currentUI *userInterface

func init() {
	if err := initialize(); err != nil {
		panic(err)
	}
}

func initialize() error {
	runtime.LockOSThread()

	if err := glfw.Init(); err != nil {
		return err
	}
	glfw.WindowHint(glfw.Visible, glfw.False)
	glfw.WindowHint(glfw.Resizable, glfw.False)
	glfw.WindowHint(glfw.ContextVersionMajor, 2)
	glfw.WindowHint(glfw.ContextVersionMinor, 1)

	// As start, create an window with temporary size to create OpenGL context thread.
	window, err := glfw.CreateWindow(16, 16, "", nil, nil)
	if err != nil {
		return err
	}
	hideConsoleWindowOnWindows()
	u := &userInterface{
		window:      window,
		funcs:       make(chan func()),
		sizeChanged: true,
		origPosX:    -1,
		origPosY:    -1,
	}
	u.window.MakeContextCurrent()
	glfw.SwapInterval(1)
	currentUI = u
	return nil
}

func RunMainThreadLoop(ch <-chan error) error {
	// TODO: Check this is done on the main thread.
	currentUI.setRunning(true)
	defer func() {
		currentUI.setRunning(false)
	}()
	for {
		select {
		case f := <-currentUI.funcs:
			f()
		case err := <-ch:
			// ch returns a value not only when an error occur but also it is closed.
			return err
		}
	}
}

func (u *userInterface) isRunning() bool {
	u.m.Lock()
	defer u.m.Unlock()
	return u.running
}

func (u *userInterface) setRunning(running bool) {
	u.m.Lock()
	defer u.m.Unlock()
	u.running = running
}

func (u *userInterface) runOnMainThread(f func() error) error {
	if u.funcs == nil {
		// already closed
		return nil
	}
	ch := make(chan struct{})
	var err error
	u.funcs <- func() {
		err = f()
		close(ch)
	}
	<-ch
	return err
}

func SetScreenSize(width, height int) bool {
	u := currentUI
	if !u.isRunning() {
		panic("ui: Run is not called yet")
	}
	r := false
	_ = u.runOnMainThread(func() error {
		r = u.setScreenSize(width, height, u.scale, u.fullscreen)
		return nil
	})
	return r
}

func SetScreenScale(scale float64) bool {
	u := currentUI
	if !u.isRunning() {
		panic("ui: Run is not called yet")
	}
	r := false
	_ = u.runOnMainThread(func() error {
		r = u.setScreenSize(u.width, u.height, scale, u.fullscreen)
		return nil
	})
	return r
}

func SetFullscreen(fullscreen bool) bool {
	u := currentUI
	if !u.isRunning() {
		panic("ui: Run is not called yet")
	}
	r := false
	_ = u.runOnMainThread(func() error {
		r = u.setScreenSize(u.width, u.height, u.scale, fullscreen)
		return nil
	})
	return r
}

func ScreenScale() float64 {
	u := currentUI
	if !u.isRunning() {
		return 0
	}
	s := 0.0
	_ = u.runOnMainThread(func() error {
		s = u.scale
		return nil
	})
	return s
}

func IsFullscreen() bool {
	u := currentUI
	if !u.isRunning() {
		return false
	}
	f := false
	_ = u.runOnMainThread(func() error {
		f = u.fullscreen
		return nil
	})
	return f
}

func SetCursorVisibility(visible bool) {
	// This can be called before Run: change the state asyncly.
	go func() {
		_ = currentUI.runOnMainThread(func() error {
			c := glfw.CursorNormal
			if !visible {
				c = glfw.CursorHidden
			}
			currentUI.window.SetInputMode(glfw.CursorMode, c)
			return nil
		})
	}()
}

func Run(width, height int, scale float64, title string, g GraphicsContext) error {
	u := currentUI
	// GLContext must be created before setting the screen size, which requires
	// swapping buffers.
	opengl.Init(currentUI.runOnMainThread)
	if err := u.runOnMainThread(func() error {
		m := glfw.GetPrimaryMonitor()
		v := m.GetVideoMode()
		if !u.setScreenSize(width, height, scale, false) {
			return errors.New("ui: Fail to set the screen size")
		}
		u.title = title
		u.window.SetTitle(title)
		u.window.Show()

		w, h := u.glfwSize()
		x := (v.Width - w) / 2
		y := (v.Height - h) / 3
		x, y = adjustWindowPosition(x, y)
		u.window.SetPos(x, y)
		return nil
	}); err != nil {
		return err
	}
	return u.loop(g)
}

func (u *userInterface) glfwSize() (int, int) {
	if u.glfwScale == 0 {
		u.glfwScale = glfwScale()
	}
	return int(float64(u.width) * u.scale * u.glfwScale), int(float64(u.height) * u.scale * u.glfwScale)
}

func (u *userInterface) getScale() float64 {
	if !u.fullscreen {
		return u.scale
	}
	if u.fullscreenScale == 0 {
		if u.glfwScale == 0 {
			u.glfwScale = glfwScale()
		}
		m := glfw.GetPrimaryMonitor()
		v := m.GetVideoMode()
		sw := float64(v.Width) / u.glfwScale / float64(u.width)
		sh := float64(v.Height) / u.glfwScale / float64(u.height)
		s := sw
		if s > sh {
			s = sh
		}
		u.fullscreenScale = s
	}
	return u.fullscreenScale
}

func (u *userInterface) actualScreenScale() float64 {
	if u.deviceScale == 0 {
		u.deviceScale = deviceScale()
	}
	return u.getScale() * u.deviceScale
}

func (u *userInterface) pollEvents() {
	glfw.PollEvents()
	if u.glfwScale == 0 {
		u.glfwScale = glfwScale()
	}
	currentInput.update(u.window, u.getScale()*u.glfwScale)
}

func (u *userInterface) update(g GraphicsContext) error {
	shouldClose := false
	_ = u.runOnMainThread(func() error {
		shouldClose = u.window.ShouldClose()
		return nil
	})
	if shouldClose {
		return &RegularTermination{}
	}

	actualScale := 0.0
	sizeChanged := false
	_ = u.runOnMainThread(func() error {
		if !u.sizeChanged {
			return nil
		}
		u.sizeChanged = false
		actualScale = u.actualScreenScale()
		sizeChanged = true
		return nil
	})
	if sizeChanged {
		g.SetSize(u.width, u.height, actualScale)
	}

	_ = u.runOnMainThread(func() error {
		u.pollEvents()
		for u.window.GetAttrib(glfw.Focused) == 0 {
			// Wait for an arbitrary period to avoid busy loop.
			time.Sleep(time.Second / 60)
			u.pollEvents()
			if u.window.ShouldClose() {
				return nil
			}
		}
		return nil
	})
	if err := g.Update(); err != nil {
		return err
	}
	return nil
}

func (u *userInterface) loop(g GraphicsContext) error {
	defer func() {
		_ = u.runOnMainThread(func() error {
			glfw.Terminate()
			return nil
		})
	}()
	for {
		if err := u.update(g); err != nil {
			return err
		}
		// The bound framebuffer must be the default one (0) before swapping buffers.
		if err := opengl.GetContext().BindScreenFramebuffer(); err != nil {
			return err
		}
		_ = u.runOnMainThread(func() error {
			u.swapBuffers()
			return nil
		})
	}
}

func (u *userInterface) swapBuffers() {
	u.window.SwapBuffers()
}

func (u *userInterface) setScreenSize(width, height int, scale float64, fullscreen bool) bool {
	if u.width == width && u.height == height && u.scale == scale && u.fullscreen == fullscreen {
		return false
	}

	origScale := u.scale
	u.scale = scale

	// On Windows, giving a too small width doesn't call a callback (#165).
	// To prevent hanging up, return asap if the width is too small.
	// 252 is an arbitrary number and I guess this is small enough.
	// TODO: The same check should be in ui_js.go
	const minWindowWidth = 252
	if int(float64(width)*u.actualScreenScale()) < minWindowWidth {
		u.scale = origScale
		return false
	}
	if u.width != width || u.height != height {
		u.width = width
		u.height = height
		u.fullscreenScale = 0
	}

	// To make sure the current existing framebuffers are rendered,
	// swap buffers here before SetSize is called.
	u.swapBuffers()

	u.fullscreen = fullscreen

	window := u.window
	m := glfw.GetPrimaryMonitor()
	v := m.GetVideoMode()
	if u.fullscreen {
		if u.origPosX < 0 && u.origPosY < 0 {
			u.origPosX, u.origPosY = window.GetPos()
		}
		window.SetMonitor(m, 0, 0, v.Width, v.Height, v.RefreshRate)
	} else {
		if u.origPosX >= 0 && u.origPosY >= 0 {
			x := u.origPosX
			y := u.origPosY
			window.SetMonitor(nil, x, y, 16, 16, v.RefreshRate)
			u.origPosX = -1
			u.origPosY = -1
		}
		ch := make(chan struct{})
		window.SetFramebufferSizeCallback(func(_ *glfw.Window, width, height int) {
			window.SetFramebufferSizeCallback(nil)
			close(ch)
		})
		w, h := u.glfwSize()
		window.SetSize(w, h)
	event:
		for {
			glfw.PollEvents()
			select {
			case <-ch:
				break event
			default:
			}
		}
		// Window title might lost on macOS after coming back from fullscreen.
		u.window.SetTitle(u.title)
	}
	// TODO: Rename this variable?
	u.sizeChanged = true
	return true
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/ant0ine/go-json-rest/rest"
	"log"
	"net/http"
)

type Message struct {
	Body string
}

func main() {
	handler := rest.ResourceHandler{}
	err := handler.SetRoutes(
		&rest.Route{"GET", "/message", func(w rest.ResponseWriter, req *rest.Request) {
			w.WriteJson(&Message{
				Body: "Hello World!",
			})
		}},
	)
	if err != nil {
		log.Fatal(err)
	}
	log.Fatal(http.ListenAndServe(":8080", &handler))
}
<commit_msg>convert helloworld to the v3 api<commit_after>package main

import (
	"github.com/ant0ine/go-json-rest/rest"
	"log"
	"net/http"
)

type Message struct {
	Body string
}

func main() {
	router, err := rest.MakeRouter(
		&rest.Route{"GET", "/message", func(w rest.ResponseWriter, req *rest.Request) {
			w.WriteJson(&Message{
				Body: "Hello World!",
			})
		}},
	)
	if err != nil {
		log.Fatal(err)
	}

	api := rest.NewApi(router)
	api.Use(rest.DefaultDevStack...)
	log.Fatal(http.ListenAndServe(":8080", api.MakeHandler()))
}
<|endoftext|>


<commit_before>package hermes

import (
	"fmt"
	"strconv"
	"crypto/sha1"
)
type HermesFile struct {
	name string
	contents string
}
func (file *HermesFile) GenerateFileName(file_ID int, file_checksum string) {
	id_string :=""
	if file_ID < 10 {
		id_string = "0" + strconv.Itoa(file_ID)
	} else {
		id_string = strconv.Itoa(file_ID)
	}
	file_name := "Hermes_"+id_string+file_checksum
	file.name = file_name
}
func (file *HermesFile) GenerateFileContents(file_ID int) {
	file.contents = "jhfvjhdfjhfjjhjhdfvjvcvfjh";
}
func (file HermesFile) GenerateFileChecksum() string {

	file_contents := []byte(file.contents)
	hash := sha1.Sum(file_contents)
	checksum := fmt.Sprintf("%s%x","_", hash)
	return checksum;
}
func generate_file (id int) HermesFile {
	file := HermesFile{}
	file.GenerateFileContents(id)
	checksum := file.GenerateFileChecksum()
	file.GenerateFileName(id, checksum)
	return file
}
<commit_msg>Update hermes/file_gen.go<commit_after>package hermes

import (
	"fmt"
	"strconv"
	"crypto/sha1"
)
type HermesFile struct {
	name string
	contents string
}
func (file *HermesFile) GenerateFileName(file_ID int, file_checksum string) {
	id_string :=""
	if file_ID < 10 {
		id_string = "0" + strconv.Itoa(file_ID)
	} else {
		id_string = strconv.Itoa(file_ID)
	}
	file_name := "Hermes_"+id_string+file_checksum
	file.name = file_name
}
func (file *HermesFile) GenerateFileContents(file_ID int) {
	file.contents = "jhfvjhdfjhfjjhjhdfvjvcvfjh";
}
func (file HermesFile) GenerateFileChecksum() string {

	file_contents := []byte(file.contents)
	hash := sha1.Sum(file_contents)
	checksum := fmt.Sprintf("_%x", hash)
	return checksum;
}
func generate_file (id int) HermesFile {
	file := HermesFile{}
	file.GenerateFileContents(id)
	checksum := file.GenerateFileChecksum()
	file.GenerateFileName(id, checksum)
	return file
}
<|endoftext|>


<commit_before>package hive

import (
	"encoding/csv"
	"encoding/json"
	"fmt"
	"github.com/eaciit/cast"
	"github.com/eaciit/errorlib"
	"github.com/eaciit/toolkit"
	"reflect"
	"regexp"
	"strconv"
	"strings"
)

type HiveResult struct {
	Header     []string
	Result     []string
	ResultObj  interface{}
	DateFormat string
}

var JsonPart string

func (hr *HiveResult) constructHeader(header string, delimiter string) {
	var tmpHeader []string
	for _, header := range strings.Split(header, delimiter) {
		split := strings.Split(header, ".")
		if len(split) > 1 {
			tmpHeader = append(tmpHeader, strings.Trim(split[1], " '"))
		} else {
			tmpHeader = append(tmpHeader, strings.Trim(header, " '"))
		}
	}
	hr.Header = tmpHeader
}

func Parse(header []string, in interface{}, m interface{}, outputType string, dateFormat string) (e error) {
	if !toolkit.IsPointer(m) {
		return errorlib.Error("", "", "Fetch", "Model object should be pointer")
	}
	slice := false
	var ins []string
	if reflect.ValueOf(m).Elem().Kind() == reflect.Slice || toolkit.TypeName(in) == "[]string" {
		slice = true
		ins = in.([]string)
	} else {
		ins = append(ins, in.(string))
	}

	if outputType == CSV {
		var v reflect.Type

		if slice && toolkit.TypeName(m) != "*interface {}" {
			v = reflect.TypeOf(m).Elem().Elem()
		} else {
			v = reflect.TypeOf(m).Elem()
		}

		ivs := reflect.MakeSlice(reflect.SliceOf(v), 0, 0)
		for _, data := range ins {
			appendData := toolkit.M{}
			iv := reflect.New(v).Interface()
			reader := csv.NewReader(strings.NewReader(""))
			if strings.Contains(data, "','") {
				reader = csv.NewReader(strings.NewReader("\"" + strings.Trim(strings.Replace(data, "','", "\",\"", -1), "'") + "\""))
			} else {
				reader = csv.NewReader(strings.NewReader(data))
			}
			record, e := reader.Read()

			if e != nil {
				return e
			}

			if v.Kind() == reflect.Struct {
				for i := 0; i < v.NumField(); i++ {
					appendData[v.Field(i).Name] = strings.TrimSpace(record[i])
					valthis := appendData[v.Field(i).Name]
					switch v.Field(i).Type.Kind() {
					case reflect.Int:
						appendData.Set(v.Field(i).Name, cast.ToInt(valthis, cast.RoundingAuto))
					case reflect.Int16:
						appendData.Set(v.Field(i).Name, cast.ToInt(valthis, cast.RoundingAuto))
					case reflect.Int32:
						appendData.Set(v.Field(i).Name, cast.ToInt(valthis, cast.RoundingAuto))
					case reflect.Int64:
						appendData.Set(v.Field(i).Name, cast.ToInt(valthis, cast.RoundingAuto))
					case reflect.Float32:
						valf, _ := strconv.ParseFloat(valthis.(string), 32)
						appendData.Set(v.Field(i).Name, valf)
					case reflect.Float64:
						valf, _ := strconv.ParseFloat(valthis.(string), 64)
						appendData.Set(v.Field(i).Name, valf)
					case reflect.Bool:
						valf, _ := strconv.ParseBool(valthis.(string))
						appendData.Set(v.Field(i).Name, valf)
					default:
						dtype := DetectDataType(valthis.(string), dateFormat)
						if dtype == "date" {
							valf := cast.String2Date(valthis.(string), dateFormat)
							appendData.Set(v.Field(i).Name, valf)
						}
					}

				}

			} else {
				if len(header) == 0 {
					e = errorlib.Error("", "", "Parse Out", "Header cant be null because object is not struct")
					return e
				}

				for i, val := range header {
					appendData[val] = strings.TrimSpace(record[i])
					valthis := appendData[val]
					dtype := DetectDataType(valthis.(string), dateFormat)
					if dtype == "int" {
						appendData.Set(val, cast.ToInt(valthis, cast.RoundingAuto))
					} else if dtype == "float" {
						valf, _ := strconv.ParseFloat(valthis.(string), 64)
						appendData.Set(val, valf)
					} else if dtype == "date" {
						valf := cast.String2Date(valthis.(string), dateFormat)
						appendData.Set(val, valf)
					} else if dtype == "bool" {
						valf, _ := strconv.ParseBool(valthis.(string))
						appendData.Set(val, valf)
					}
				}
			}

			toolkit.Serde(appendData, iv, JSON)
			ivs = reflect.Append(ivs, reflect.ValueOf(iv).Elem())
		}
		if slice {
			reflect.ValueOf(m).Elem().Set(ivs)
		} else {
			reflect.ValueOf(m).Elem().Set(ivs.Index(0))
		}
	} else if outputType == JSON {
		var temp interface{}
		ins = InspectJson(ins)

		//for catch multi json in one line
		if JsonPart != "" && slice {
			for {
				tempjsonpart := JsonPart
				JsonPart = ""
				tempIn := InspectJson([]string{tempjsonpart})
				if len(tempIn) == 0 {
					break
				} else {
					for _, tin := range tempIn {
						ins = append(ins, tin)
					}
				}
			}
		}

		forSerde := strings.Join(ins, ",")
		if slice {
			forSerde = fmt.Sprintf("[%s]", strings.Join(ins, ","))
		}
		if len(ins) > 0 {
			e := json.Unmarshal([]byte(forSerde), &temp)
			if e != nil {
				return e
			}
			e = toolkit.Serde(temp, m, "json")
			if e != nil {
				return e
			}
		}
	} else {
		var v reflect.Type

		if slice && toolkit.TypeName(m) != "*interface {}" {
			v = reflect.TypeOf(m).Elem().Elem()
		} else {
			v = reflect.TypeOf(m).Elem()
		}

		ivs := reflect.MakeSlice(reflect.SliceOf(v), 0, 0)

		for _, data := range ins {
			appendData := toolkit.M{}
			iv := reflect.New(v).Interface()

			splitted := strings.Split(data, "\t")

			if v.Kind() == reflect.Struct {
				for i := 0; i < v.NumField(); i++ {
					appendData[v.Field(i).Name] = strings.TrimSpace(strings.Trim(splitted[i], " '"))
					valthis := appendData[v.Field(i).Name]
					switch v.Field(i).Type.Kind() {
					case reflect.Int:
						appendData.Set(v.Field(i).Name, cast.ToInt(valthis, cast.RoundingAuto))
					case reflect.Int16:
						appendData.Set(v.Field(i).Name, cast.ToInt(valthis, cast.RoundingAuto))
					case reflect.Int32:
						appendData.Set(v.Field(i).Name, cast.ToInt(valthis, cast.RoundingAuto))
					case reflect.Int64:
						appendData.Set(v.Field(i).Name, cast.ToInt(valthis, cast.RoundingAuto))
					case reflect.Float32:
						valf, _ := strconv.ParseFloat(valthis.(string), 32)
						appendData.Set(v.Field(i).Name, valf)
					case reflect.Float64:
						valf, _ := strconv.ParseFloat(valthis.(string), 64)
						appendData.Set(v.Field(i).Name, valf)
					case reflect.Bool:
						valf, _ := strconv.ParseBool(valthis.(string))
						appendData.Set(v.Field(i).Name, valf)
					default:
						dtype := DetectDataType(valthis.(string), dateFormat)
						if dtype == "date" {
							valf := cast.String2Date(valthis.(string), dateFormat)
							appendData.Set(v.Field(i).Name, valf)
						}
					}

				}

			} else {

				if len(header) == 0 {
					e = errorlib.Error("", "", "Parse Out", "Header cant be null because object is not struct")
					return e
				}

				for i, val := range header {
					appendData[val] = strings.TrimSpace(strings.Trim(splitted[i], " '"))
					valthis := appendData[val]
					dtype := DetectDataType(valthis.(string), dateFormat)
					if dtype == "int" {
						appendData.Set(val, cast.ToInt(valthis, cast.RoundingAuto))
					} else if dtype == "float" {
						valf, _ := strconv.ParseFloat(valthis.(string), 64)
						appendData.Set(val, valf)
					} else if dtype == "date" {
						valf := cast.String2Date(valthis.(string), dateFormat)
						appendData.Set(val, valf)
					} else if dtype == "bool" {
						valf, _ := strconv.ParseBool(valthis.(string))
						appendData.Set(val, valf)
					}
				}
			}

			toolkit.Serde(appendData, iv, JSON)
			ivs = reflect.Append(ivs, reflect.ValueOf(iv).Elem())
		}

		if slice {
			reflect.ValueOf(m).Elem().Set(ivs)
		} else {
			reflect.ValueOf(m).Elem().Set(ivs.Index(0))
		}
	}
	return nil
}

func InspectJson(ins []string) (out []string) {
	var re []string

	for _, in := range ins {
		if JsonPart != "" {
			in = JsonPart + in
		}
		in = strings.Trim(strings.TrimSpace(in), " ,")
		charopen := 0
		charclose := 0
		for i, r := range in {
			c := string(r)
			if c == "{" {
				charopen += 1
			} else if c == "}" {
				charclose += 1
			}

			if charopen == charclose && (charclose != 0 && charopen != 0) {
				if len(in) == i+1 {
					JsonPart = ""
				} else {
					JsonPart = in[i+1:]
				}
				re = append(re, strings.Trim(strings.TrimSpace(in[:i+1]), " ,"))
				break
			}
			if charopen != charclose || (charclose == 0 && charopen == 0) {
				JsonPart = in
			}
		}

	}
	return re
}

func DetectDataType(in string, dateFormat string) (res string) {
	if in != "" {
		matchNumber := false
		matchFloat := false
		matchDate := false

		formatDate := "((^(0[0-9]|[0-9]|(1|2)[0-9]|3[0-1])(\\.|\\/|-)(0[0-9]|[0-9]|1[0-2])(\\.|\\/|-)[\\d]{4}$)|(^[\\d]{4}(\\.|\\/|-)(0[0-9]|[0-9]|1[0-2])(\\.|\\/|-)(0[0-9]|[0-9]|(1|2)[0-9]|3[0-1])$))"
		matchDate, _ = regexp.MatchString(formatDate, in)

		if !matchDate && dateFormat != "" {
			d := cast.String2Date(in, dateFormat)
			if d.Year() > 1 {
				matchDate = true
			}
		}

		x := strings.Index(in, ".")

		if x > 0 {
			matchFloat = true
			in = strings.Replace(in, ".", "", 1)
		}

		matchNumber, _ = regexp.MatchString("^\\d+$", in)

		if strings.TrimSpace(in) == "true" || strings.TrimSpace(in) == "false" {
			res = "bool"
		} else {
			res = "string"
			if matchNumber {
				res = "int"
				if matchFloat {
					res = "float"
				}
			}

			if matchDate {
				res = "date"
			}
		}
	}
	return res
}

type FieldMismatch struct {
	expected, found int
}

func (e *FieldMismatch) Error() string {
	return "CSV line fields mismatch. Expected " + strconv.Itoa(e.expected) + " found " + strconv.Itoa(e.found)
}

type UnsupportedType struct {
	Type string
}

func (e *UnsupportedType) Error() string {
	return "Unsupported type: " + e.Type
}
<commit_msg>fix bugs inspect json<commit_after>package hive

import (
	"encoding/csv"
	"encoding/json"
	"fmt"
	"github.com/eaciit/cast"
	"github.com/eaciit/errorlib"
	"github.com/eaciit/toolkit"
	"reflect"
	"regexp"
	"strconv"
	"strings"
)

type HiveResult struct {
	Header     []string
	Result     []string
	ResultObj  interface{}
	DateFormat string
}

var JsonPart string

func (hr *HiveResult) constructHeader(header string, delimiter string) {
	var tmpHeader []string
	for _, header := range strings.Split(header, delimiter) {
		split := strings.Split(header, ".")
		if len(split) > 1 {
			tmpHeader = append(tmpHeader, strings.Trim(split[1], " '"))
		} else {
			tmpHeader = append(tmpHeader, strings.Trim(header, " '"))
		}
	}
	hr.Header = tmpHeader
}

func Parse(header []string, in interface{}, m interface{}, outputType string, dateFormat string) (e error) {
	if !toolkit.IsPointer(m) {
		return errorlib.Error("", "", "Fetch", "Model object should be pointer")
	}
	slice := false
	var ins []string
	if reflect.ValueOf(m).Elem().Kind() == reflect.Slice || toolkit.TypeName(in) == "[]string" {
		slice = true
		ins = in.([]string)
	} else {
		ins = append(ins, in.(string))
	}

	if outputType == CSV {
		var v reflect.Type

		if slice && toolkit.TypeName(m) != "*interface {}" {
			v = reflect.TypeOf(m).Elem().Elem()
		} else {
			v = reflect.TypeOf(m).Elem()
		}

		ivs := reflect.MakeSlice(reflect.SliceOf(v), 0, 0)
		for _, data := range ins {
			appendData := toolkit.M{}
			iv := reflect.New(v).Interface()
			reader := csv.NewReader(strings.NewReader(""))
			if strings.Contains(data, "','") {
				reader = csv.NewReader(strings.NewReader("\"" + strings.Trim(strings.Replace(data, "','", "\",\"", -1), "'") + "\""))
			} else {
				reader = csv.NewReader(strings.NewReader(data))
			}
			record, e := reader.Read()

			if e != nil {
				return e
			}

			if v.Kind() == reflect.Struct {
				for i := 0; i < v.NumField(); i++ {
					appendData[v.Field(i).Name] = strings.TrimSpace(record[i])
					valthis := appendData[v.Field(i).Name]
					switch v.Field(i).Type.Kind() {
					case reflect.Int:
						appendData.Set(v.Field(i).Name, cast.ToInt(valthis, cast.RoundingAuto))
					case reflect.Int16:
						appendData.Set(v.Field(i).Name, cast.ToInt(valthis, cast.RoundingAuto))
					case reflect.Int32:
						appendData.Set(v.Field(i).Name, cast.ToInt(valthis, cast.RoundingAuto))
					case reflect.Int64:
						appendData.Set(v.Field(i).Name, cast.ToInt(valthis, cast.RoundingAuto))
					case reflect.Float32:
						valf, _ := strconv.ParseFloat(valthis.(string), 32)
						appendData.Set(v.Field(i).Name, valf)
					case reflect.Float64:
						valf, _ := strconv.ParseFloat(valthis.(string), 64)
						appendData.Set(v.Field(i).Name, valf)
					case reflect.Bool:
						valf, _ := strconv.ParseBool(valthis.(string))
						appendData.Set(v.Field(i).Name, valf)
					default:
						dtype := DetectDataType(valthis.(string), dateFormat)
						if dtype == "date" {
							valf := cast.String2Date(valthis.(string), dateFormat)
							appendData.Set(v.Field(i).Name, valf)
						}
					}

				}

			} else {
				if len(header) == 0 {
					e = errorlib.Error("", "", "Parse Out", "Header cant be null because object is not struct")
					return e
				}

				for i, val := range header {
					appendData[val] = strings.TrimSpace(record[i])
					valthis := appendData[val]
					dtype := DetectDataType(valthis.(string), dateFormat)
					if dtype == "int" {
						appendData.Set(val, cast.ToInt(valthis, cast.RoundingAuto))
					} else if dtype == "float" {
						valf, _ := strconv.ParseFloat(valthis.(string), 64)
						appendData.Set(val, valf)
					} else if dtype == "date" {
						valf := cast.String2Date(valthis.(string), dateFormat)
						appendData.Set(val, valf)
					} else if dtype == "bool" {
						valf, _ := strconv.ParseBool(valthis.(string))
						appendData.Set(val, valf)
					}
				}
			}

			toolkit.Serde(appendData, iv, JSON)
			ivs = reflect.Append(ivs, reflect.ValueOf(iv).Elem())
		}
		if slice {
			reflect.ValueOf(m).Elem().Set(ivs)
		} else {
			reflect.ValueOf(m).Elem().Set(ivs.Index(0))
		}
	} else if outputType == JSON {
		var temp interface{}
		ins = InspectJson(ins)

		//for catch multi json in one line
		if JsonPart != "" && slice {
			for {
				tempjsonpart := JsonPart
				JsonPart = ""
				tempIn := InspectJson([]string{tempjsonpart})
				if len(tempIn) == 0 {
					break
				} else {
					for _, tin := range tempIn {
						ins = append(ins, tin)
					}
				}
			}
		}

		forSerde := strings.Join(ins, ",")
		if slice {
			forSerde = fmt.Sprintf("[%s]", strings.Join(ins, ","))
		}
		if len(ins) > 0 {
			e := json.Unmarshal([]byte(forSerde), &temp)
			if e != nil {
				return e
			}
			e = toolkit.Serde(temp, m, "json")
			if e != nil {
				return e
			}
		}
	} else {
		var v reflect.Type

		if slice && toolkit.TypeName(m) != "*interface {}" {
			v = reflect.TypeOf(m).Elem().Elem()
		} else {
			v = reflect.TypeOf(m).Elem()
		}

		ivs := reflect.MakeSlice(reflect.SliceOf(v), 0, 0)

		for _, data := range ins {
			appendData := toolkit.M{}
			iv := reflect.New(v).Interface()

			splitted := strings.Split(data, "\t")

			if v.Kind() == reflect.Struct {
				for i := 0; i < v.NumField(); i++ {
					appendData[v.Field(i).Name] = strings.TrimSpace(strings.Trim(splitted[i], " '"))
					valthis := appendData[v.Field(i).Name]
					switch v.Field(i).Type.Kind() {
					case reflect.Int:
						appendData.Set(v.Field(i).Name, cast.ToInt(valthis, cast.RoundingAuto))
					case reflect.Int16:
						appendData.Set(v.Field(i).Name, cast.ToInt(valthis, cast.RoundingAuto))
					case reflect.Int32:
						appendData.Set(v.Field(i).Name, cast.ToInt(valthis, cast.RoundingAuto))
					case reflect.Int64:
						appendData.Set(v.Field(i).Name, cast.ToInt(valthis, cast.RoundingAuto))
					case reflect.Float32:
						valf, _ := strconv.ParseFloat(valthis.(string), 32)
						appendData.Set(v.Field(i).Name, valf)
					case reflect.Float64:
						valf, _ := strconv.ParseFloat(valthis.(string), 64)
						appendData.Set(v.Field(i).Name, valf)
					case reflect.Bool:
						valf, _ := strconv.ParseBool(valthis.(string))
						appendData.Set(v.Field(i).Name, valf)
					default:
						dtype := DetectDataType(valthis.(string), dateFormat)
						if dtype == "date" {
							valf := cast.String2Date(valthis.(string), dateFormat)
							appendData.Set(v.Field(i).Name, valf)
						}
					}

				}

			} else {

				if len(header) == 0 {
					e = errorlib.Error("", "", "Parse Out", "Header cant be null because object is not struct")
					return e
				}

				for i, val := range header {
					appendData[val] = strings.TrimSpace(strings.Trim(splitted[i], " '"))
					valthis := appendData[val]
					dtype := DetectDataType(valthis.(string), dateFormat)
					if dtype == "int" {
						appendData.Set(val, cast.ToInt(valthis, cast.RoundingAuto))
					} else if dtype == "float" {
						valf, _ := strconv.ParseFloat(valthis.(string), 64)
						appendData.Set(val, valf)
					} else if dtype == "date" {
						valf := cast.String2Date(valthis.(string), dateFormat)
						appendData.Set(val, valf)
					} else if dtype == "bool" {
						valf, _ := strconv.ParseBool(valthis.(string))
						appendData.Set(val, valf)
					}
				}
			}

			toolkit.Serde(appendData, iv, JSON)
			ivs = reflect.Append(ivs, reflect.ValueOf(iv).Elem())
		}

		if slice {
			reflect.ValueOf(m).Elem().Set(ivs)
		} else {
			reflect.ValueOf(m).Elem().Set(ivs.Index(0))
		}
	}
	return nil
}

func InspectJson(ins []string) (out []string) {
	var re []string

	for _, in := range ins {
		if JsonPart != "" {
			in = JsonPart + in
		}
		in = strings.TrimSpace(in)
		charopen := 0
		charclose := 0
		for i, r := range in {
			c := string(r)
			if c == "{" {
				charopen += 1
			} else if c == "}" {
				charclose += 1
			}

			if charopen == charclose && (charclose != 0 && charopen != 0) {
				if len(in) == i+1 {
					JsonPart = ""
				} else {
					JsonPart = in[i+1:]
				}
				re = append(re, strings.Trim(strings.TrimSpace(in[:i+1]), " ,"))
				break
			}
			if charopen != charclose || (charclose == 0 && charopen == 0) {
				JsonPart = in
			}
		}

	}
	return re
}

func DetectDataType(in string, dateFormat string) (res string) {
	if in != "" {
		matchNumber := false
		matchFloat := false
		matchDate := false

		formatDate := "((^(0[0-9]|[0-9]|(1|2)[0-9]|3[0-1])(\\.|\\/|-)(0[0-9]|[0-9]|1[0-2])(\\.|\\/|-)[\\d]{4}$)|(^[\\d]{4}(\\.|\\/|-)(0[0-9]|[0-9]|1[0-2])(\\.|\\/|-)(0[0-9]|[0-9]|(1|2)[0-9]|3[0-1])$))"
		matchDate, _ = regexp.MatchString(formatDate, in)

		if !matchDate && dateFormat != "" {
			d := cast.String2Date(in, dateFormat)
			if d.Year() > 1 {
				matchDate = true
			}
		}

		x := strings.Index(in, ".")

		if x > 0 {
			matchFloat = true
			in = strings.Replace(in, ".", "", 1)
		}

		matchNumber, _ = regexp.MatchString("^\\d+$", in)

		if strings.TrimSpace(in) == "true" || strings.TrimSpace(in) == "false" {
			res = "bool"
		} else {
			res = "string"
			if matchNumber {
				res = "int"
				if matchFloat {
					res = "float"
				}
			}

			if matchDate {
				res = "date"
			}
		}
	}
	return res
}

type FieldMismatch struct {
	expected, found int
}

func (e *FieldMismatch) Error() string {
	return "CSV line fields mismatch. Expected " + strconv.Itoa(e.expected) + " found " + strconv.Itoa(e.found)
}

type UnsupportedType struct {
	Type string
}

func (e *UnsupportedType) Error() string {
	return "Unsupported type: " + e.Type
}
<|endoftext|>


<commit_before>// Copyright 2014 CoreOS, Inc.
//
// 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 functional

import (
	"io/ioutil"
	"path"
	"strings"
	"testing"

	"github.com/coreos/fleet/functional/platform"
)

// TestUnitRunnable is the simplest test possible, deplying a single-node
// cluster and ensuring a unit can enter an 'active' state
func TestUnitRunnable(t *testing.T) {
	cluster, err := platform.NewNspawnCluster("smoke")
	if err != nil {
		t.Fatal(err)
	}
	defer cluster.Destroy()

	m0, err := cluster.CreateMember()
	if err != nil {
		t.Fatal(err)
	}
	_, err = cluster.WaitForNMachines(m0, 1)
	if err != nil {
		t.Fatal(err)
	}

	if stdout, stderr, err := cluster.Fleetctl(m0, "start", "fixtures/units/hello.service"); err != nil {
		t.Fatalf("Unable to start fleet unit: \nstdout: %s\nstderr: %s\nerr: %v", stdout, stderr, err)
	}

	units, err := cluster.WaitForNActiveUnits(m0, 1)
	if err != nil {
		t.Fatal(err)
	}
	_, found := units["hello.service"]
	if len(units) != 1 || !found {
		t.Fatalf("Expected hello.service to be sole active unit, got %v", units)
	}
}

func TestUnitSubmit(t *testing.T) {
	cluster, err := platform.NewNspawnCluster("smoke")
	if err != nil {
		t.Fatal(err)
	}
	defer cluster.Destroy()

	m, err := cluster.CreateMember()
	if err != nil {
		t.Fatal(err)
	}
	_, err = cluster.WaitForNMachines(m, 1)
	if err != nil {
		t.Fatal(err)
	}

	// submit a unit and assert it shows up
	if _, _, err := cluster.Fleetctl(m, "submit", "fixtures/units/hello.service"); err != nil {
		t.Fatalf("Unable to submit fleet unit: %v", err)
	}
	stdout, _, err := cluster.Fleetctl(m, "list-units", "--no-legend")
	if err != nil {
		t.Fatalf("Failed to run list-units: %v", err)
	}
	units := strings.Split(strings.TrimSpace(stdout), "\n")
	if len(units) != 1 {
		t.Fatalf("Did not find 1 unit in cluster: \n%s", stdout)
	}

	// submitting the same unit should not fail
	if _, _, err = cluster.Fleetctl(m, "submit", "fixtures/units/hello.service"); err != nil {
		t.Fatalf("Expected no failure when double-submitting unit, got this: %v", err)
	}

	// destroy the unit and ensure it disappears from the unit list
	if _, _, err := cluster.Fleetctl(m, "destroy", "fixtures/units/hello.service"); err != nil {
		t.Fatalf("Failed to destroy unit: %v", err)
	}
	stdout, _, err = cluster.Fleetctl(m, "list-units", "--no-legend")
	if err != nil {
		t.Fatalf("Failed to run list-units: %v", err)
	}
	if strings.TrimSpace(stdout) != "" {
		t.Fatalf("Did not find 0 units in cluster: \n%s", stdout)
	}

	// submitting the unit after destruction should succeed
	if _, _, err := cluster.Fleetctl(m, "submit", "fixtures/units/hello.service"); err != nil {
		t.Fatalf("Unable to submit fleet unit: %v", err)
	}
	stdout, _, err = cluster.Fleetctl(m, "list-units", "--no-legend")
	if err != nil {
		t.Fatalf("Failed to run list-units: %v", err)
	}
	units = strings.Split(strings.TrimSpace(stdout), "\n")
	if len(units) != 1 {
		t.Fatalf("Did not find 1 unit in cluster: \n%s", stdout)
	}
}

func TestUnitRestart(t *testing.T) {
	cluster, err := platform.NewNspawnCluster("smoke")
	if err != nil {
		t.Fatal(err)
	}
	defer cluster.Destroy()

	m, err := cluster.CreateMember()
	if err != nil {
		t.Fatal(err)
	}
	_, err = cluster.WaitForNMachines(m, 1)
	if err != nil {
		t.Fatal(err)
	}

	if stdout, stderr, err := cluster.Fleetctl(m, "start", "fixtures/units/hello.service"); err != nil {
		t.Fatalf("Unable to start fleet unit: \nstdout: %s\nstderr: %s\nerr: %v", stdout, stderr, err)
	}

	units, err := cluster.WaitForNActiveUnits(m, 1)
	if err != nil {
		t.Fatal(err)
	}
	_, found := units["hello.service"]
	if len(units) != 1 || !found {
		t.Fatalf("Expected hello.service to be sole active unit, got %v", units)
	}

	if _, _, err := cluster.Fleetctl(m, "stop", "hello.service"); err != nil {
		t.Fatal(err)
	}
	units, err = cluster.WaitForNActiveUnits(m, 0)
	if err != nil {
		t.Fatal(err)
	}
	if len(units) != 0 {
		t.Fatalf("Zero units should be running, found %v", units)
	}

	if stdout, stderr, err := cluster.Fleetctl(m, "start", "hello.service"); err != nil {
		t.Fatalf("Unable to start fleet unit: \nstdout: %s\nstderr: %s\nerr: %v", stdout, stderr, err)
	}
	units, err = cluster.WaitForNActiveUnits(m, 1)
	if err != nil {
		t.Fatal(err)
	}
	_, found = units["hello.service"]
	if len(units) != 1 || !found {
		t.Fatalf("Expected hello.service to be sole active unit, got %v", units)
	}

}

func TestUnitSSHActions(t *testing.T) {
	cluster, err := platform.NewNspawnCluster("smoke")
	if err != nil {
		t.Fatal(err)
	}
	defer cluster.Destroy()

	m, err := cluster.CreateMember()
	if err != nil {
		t.Fatal(err)
	}
	_, err = cluster.WaitForNMachines(m, 1)
	if err != nil {
		t.Fatal(err)
	}

	if stdout, stderr, err := cluster.Fleetctl(m, "start", "--no-block", "fixtures/units/hello.service"); err != nil {
		t.Fatalf("Unable to start fleet unit: \nstdout: %s\nstderr: %s\nerr: %v", stdout, stderr, err)
	}

	units, err := cluster.WaitForNActiveUnits(m, 1)
	if err != nil {
		t.Fatal(err)
	}

	_, found := units["hello.service"]
	if len(units) != 1 || !found {
		t.Fatalf("Expected hello.service to be sole active unit, got %v", units)
	}

	stdout, stderr, err := cluster.Fleetctl(m, "--strict-host-key-checking=false", "ssh", "hello.service", "echo", "foo")
	if err != nil {
		t.Errorf("Failure occurred while calling fleetctl ssh: %v\nstdout: %v\nstderr: %v", err, stdout, stderr)
	}

	if !strings.Contains(stdout, "foo") {
		t.Errorf("Could not find expected string in command output:\n%s", stdout)
	}

	stdout, stderr, err = cluster.Fleetctl(m, "--strict-host-key-checking=false", "status", "hello.service")
	if err != nil {
		t.Errorf("Failure occurred while calling fleetctl status: %v\nstdout: %v\nstderr: %v", err, stdout, stderr)
	}

	if !strings.Contains(stdout, "Active: active") {
		t.Errorf("Could not find expected string in status output:\n%s", stdout)
	}

	stdout, stderr, err = cluster.Fleetctl(m, "--strict-host-key-checking=false", "journal", "--sudo", "hello.service")
	if err != nil {
		t.Errorf("Failure occurred while calling fleetctl journal: %v\nstdout: %v\nstderr: %v", err, stdout, stderr)
	}

	if !strings.Contains(stdout, "Hello, World!") {
		t.Errorf("Could not find expected string in journal output:\n%s", stdout)
	}
}

// TestUnitCat simply compares body of a unit file with that of a unit fetched
// from the remote cluster using "fleetctl cat".
func TestUnitCat(t *testing.T) {
	cluster, err := platform.NewNspawnCluster("smoke")
	if err != nil {
		t.Fatal(err)
	}
	defer cluster.Destroy()

	m, err := cluster.CreateMember()
	if err != nil {
		t.Fatal(err)
	}
	_, err = cluster.WaitForNMachines(m, 1)
	if err != nil {
		t.Fatal(err)
	}

	// read a sample unit file to a buffer
	unitFile := "fixtures/units/hello.service"
	fileBuf, err := ioutil.ReadFile(unitFile)
	if err != nil {
		t.Fatal(err)
	}
	fileBody := strings.TrimSpace(string(fileBuf))

	// submit a unit and assert it shows up
	_, _, err = cluster.Fleetctl(m, "submit", unitFile)
	if err != nil {
		t.Fatalf("Unable to submit fleet unit: %v", err)
	}
	// wait until the unit gets submitted up to 15 seconds
	_, err = cluster.WaitForNUnitFiles(m, 1)
	if err != nil {
		t.Fatalf("Failed to run list-units: %v", err)
	}

	// cat the unit file and compare it with the original unit body
	stdout, _, err := cluster.Fleetctl(m, "cat", path.Base(unitFile))
	if err != nil {
		t.Fatalf("Unable to submit fleet unit: %v", err)
	}
	catBody := strings.TrimSpace(stdout)

	if strings.Compare(catBody, fileBody) != 0 {
		t.Fatalf("unit body changed across fleetctl cat: \noriginal:%s\nnew:%s", fileBody, catBody)
	}
}
<commit_msg>functional: introduce a new test TestUnitStatus<commit_after>// Copyright 2014 CoreOS, Inc.
//
// 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 functional

import (
	"io/ioutil"
	"path"
	"strings"
	"testing"

	"github.com/coreos/fleet/functional/platform"
)

// TestUnitRunnable is the simplest test possible, deplying a single-node
// cluster and ensuring a unit can enter an 'active' state
func TestUnitRunnable(t *testing.T) {
	cluster, err := platform.NewNspawnCluster("smoke")
	if err != nil {
		t.Fatal(err)
	}
	defer cluster.Destroy()

	m0, err := cluster.CreateMember()
	if err != nil {
		t.Fatal(err)
	}
	_, err = cluster.WaitForNMachines(m0, 1)
	if err != nil {
		t.Fatal(err)
	}

	if stdout, stderr, err := cluster.Fleetctl(m0, "start", "fixtures/units/hello.service"); err != nil {
		t.Fatalf("Unable to start fleet unit: \nstdout: %s\nstderr: %s\nerr: %v", stdout, stderr, err)
	}

	units, err := cluster.WaitForNActiveUnits(m0, 1)
	if err != nil {
		t.Fatal(err)
	}
	_, found := units["hello.service"]
	if len(units) != 1 || !found {
		t.Fatalf("Expected hello.service to be sole active unit, got %v", units)
	}
}

func TestUnitSubmit(t *testing.T) {
	cluster, err := platform.NewNspawnCluster("smoke")
	if err != nil {
		t.Fatal(err)
	}
	defer cluster.Destroy()

	m, err := cluster.CreateMember()
	if err != nil {
		t.Fatal(err)
	}
	_, err = cluster.WaitForNMachines(m, 1)
	if err != nil {
		t.Fatal(err)
	}

	// submit a unit and assert it shows up
	if _, _, err := cluster.Fleetctl(m, "submit", "fixtures/units/hello.service"); err != nil {
		t.Fatalf("Unable to submit fleet unit: %v", err)
	}
	stdout, _, err := cluster.Fleetctl(m, "list-units", "--no-legend")
	if err != nil {
		t.Fatalf("Failed to run list-units: %v", err)
	}
	units := strings.Split(strings.TrimSpace(stdout), "\n")
	if len(units) != 1 {
		t.Fatalf("Did not find 1 unit in cluster: \n%s", stdout)
	}

	// submitting the same unit should not fail
	if _, _, err = cluster.Fleetctl(m, "submit", "fixtures/units/hello.service"); err != nil {
		t.Fatalf("Expected no failure when double-submitting unit, got this: %v", err)
	}

	// destroy the unit and ensure it disappears from the unit list
	if _, _, err := cluster.Fleetctl(m, "destroy", "fixtures/units/hello.service"); err != nil {
		t.Fatalf("Failed to destroy unit: %v", err)
	}
	stdout, _, err = cluster.Fleetctl(m, "list-units", "--no-legend")
	if err != nil {
		t.Fatalf("Failed to run list-units: %v", err)
	}
	if strings.TrimSpace(stdout) != "" {
		t.Fatalf("Did not find 0 units in cluster: \n%s", stdout)
	}

	// submitting the unit after destruction should succeed
	if _, _, err := cluster.Fleetctl(m, "submit", "fixtures/units/hello.service"); err != nil {
		t.Fatalf("Unable to submit fleet unit: %v", err)
	}
	stdout, _, err = cluster.Fleetctl(m, "list-units", "--no-legend")
	if err != nil {
		t.Fatalf("Failed to run list-units: %v", err)
	}
	units = strings.Split(strings.TrimSpace(stdout), "\n")
	if len(units) != 1 {
		t.Fatalf("Did not find 1 unit in cluster: \n%s", stdout)
	}
}

func TestUnitRestart(t *testing.T) {
	cluster, err := platform.NewNspawnCluster("smoke")
	if err != nil {
		t.Fatal(err)
	}
	defer cluster.Destroy()

	m, err := cluster.CreateMember()
	if err != nil {
		t.Fatal(err)
	}
	_, err = cluster.WaitForNMachines(m, 1)
	if err != nil {
		t.Fatal(err)
	}

	if stdout, stderr, err := cluster.Fleetctl(m, "start", "fixtures/units/hello.service"); err != nil {
		t.Fatalf("Unable to start fleet unit: \nstdout: %s\nstderr: %s\nerr: %v", stdout, stderr, err)
	}

	units, err := cluster.WaitForNActiveUnits(m, 1)
	if err != nil {
		t.Fatal(err)
	}
	_, found := units["hello.service"]
	if len(units) != 1 || !found {
		t.Fatalf("Expected hello.service to be sole active unit, got %v", units)
	}

	if _, _, err := cluster.Fleetctl(m, "stop", "hello.service"); err != nil {
		t.Fatal(err)
	}
	units, err = cluster.WaitForNActiveUnits(m, 0)
	if err != nil {
		t.Fatal(err)
	}
	if len(units) != 0 {
		t.Fatalf("Zero units should be running, found %v", units)
	}

	if stdout, stderr, err := cluster.Fleetctl(m, "start", "hello.service"); err != nil {
		t.Fatalf("Unable to start fleet unit: \nstdout: %s\nstderr: %s\nerr: %v", stdout, stderr, err)
	}
	units, err = cluster.WaitForNActiveUnits(m, 1)
	if err != nil {
		t.Fatal(err)
	}
	_, found = units["hello.service"]
	if len(units) != 1 || !found {
		t.Fatalf("Expected hello.service to be sole active unit, got %v", units)
	}

}

func TestUnitSSHActions(t *testing.T) {
	cluster, err := platform.NewNspawnCluster("smoke")
	if err != nil {
		t.Fatal(err)
	}
	defer cluster.Destroy()

	m, err := cluster.CreateMember()
	if err != nil {
		t.Fatal(err)
	}
	_, err = cluster.WaitForNMachines(m, 1)
	if err != nil {
		t.Fatal(err)
	}

	if stdout, stderr, err := cluster.Fleetctl(m, "start", "--no-block", "fixtures/units/hello.service"); err != nil {
		t.Fatalf("Unable to start fleet unit: \nstdout: %s\nstderr: %s\nerr: %v", stdout, stderr, err)
	}

	units, err := cluster.WaitForNActiveUnits(m, 1)
	if err != nil {
		t.Fatal(err)
	}

	_, found := units["hello.service"]
	if len(units) != 1 || !found {
		t.Fatalf("Expected hello.service to be sole active unit, got %v", units)
	}

	stdout, stderr, err := cluster.Fleetctl(m, "--strict-host-key-checking=false", "ssh", "hello.service", "echo", "foo")
	if err != nil {
		t.Errorf("Failure occurred while calling fleetctl ssh: %v\nstdout: %v\nstderr: %v", err, stdout, stderr)
	}

	if !strings.Contains(stdout, "foo") {
		t.Errorf("Could not find expected string in command output:\n%s", stdout)
	}

	stdout, stderr, err = cluster.Fleetctl(m, "--strict-host-key-checking=false", "status", "hello.service")
	if err != nil {
		t.Errorf("Failure occurred while calling fleetctl status: %v\nstdout: %v\nstderr: %v", err, stdout, stderr)
	}

	if !strings.Contains(stdout, "Active: active") {
		t.Errorf("Could not find expected string in status output:\n%s", stdout)
	}

	stdout, stderr, err = cluster.Fleetctl(m, "--strict-host-key-checking=false", "journal", "--sudo", "hello.service")
	if err != nil {
		t.Errorf("Failure occurred while calling fleetctl journal: %v\nstdout: %v\nstderr: %v", err, stdout, stderr)
	}

	if !strings.Contains(stdout, "Hello, World!") {
		t.Errorf("Could not find expected string in journal output:\n%s", stdout)
	}
}

// TestUnitCat simply compares body of a unit file with that of a unit fetched
// from the remote cluster using "fleetctl cat".
func TestUnitCat(t *testing.T) {
	cluster, err := platform.NewNspawnCluster("smoke")
	if err != nil {
		t.Fatal(err)
	}
	defer cluster.Destroy()

	m, err := cluster.CreateMember()
	if err != nil {
		t.Fatal(err)
	}
	_, err = cluster.WaitForNMachines(m, 1)
	if err != nil {
		t.Fatal(err)
	}

	// read a sample unit file to a buffer
	unitFile := "fixtures/units/hello.service"
	fileBuf, err := ioutil.ReadFile(unitFile)
	if err != nil {
		t.Fatal(err)
	}
	fileBody := strings.TrimSpace(string(fileBuf))

	// submit a unit and assert it shows up
	_, _, err = cluster.Fleetctl(m, "submit", unitFile)
	if err != nil {
		t.Fatalf("Unable to submit fleet unit: %v", err)
	}
	// wait until the unit gets submitted up to 15 seconds
	_, err = cluster.WaitForNUnitFiles(m, 1)
	if err != nil {
		t.Fatalf("Failed to run list-units: %v", err)
	}

	// cat the unit file and compare it with the original unit body
	stdout, _, err := cluster.Fleetctl(m, "cat", path.Base(unitFile))
	if err != nil {
		t.Fatalf("Unable to submit fleet unit: %v", err)
	}
	catBody := strings.TrimSpace(stdout)

	if strings.Compare(catBody, fileBody) != 0 {
		t.Fatalf("unit body changed across fleetctl cat: \noriginal:%s\nnew:%s", fileBody, catBody)
	}
}

// TestUnitStatus simply checks "fleetctl status hello.service" actually works.
func TestUnitStatus(t *testing.T) {
	cluster, err := platform.NewNspawnCluster("smoke")
	if err != nil {
		t.Fatal(err)
	}
	defer cluster.Destroy()

	m, err := cluster.CreateMember()
	if err != nil {
		t.Fatal(err)
	}
	_, err = cluster.WaitForNMachines(m, 1)
	if err != nil {
		t.Fatal(err)
	}

	unitFile := "fixtures/units/hello.service"

	// Load a unit and print out status.
	// Without loading a unit, it's impossible to run fleetctl status
	_, _, err = cluster.Fleetctl(m, "load", unitFile)
	if err != nil {
		t.Fatalf("Unable to load a fleet unit: %v", err)
	}

	// wait until the unit gets loaded up to 15 seconds
	_, err = cluster.WaitForNUnits(m, 1)
	if err != nil {
		t.Fatalf("Failed to run list-units: %v", err)
	}

	stdout, stderr, err := cluster.Fleetctl(m,
		"--strict-host-key-checking=false", "status", path.Base(unitFile))
	if !strings.Contains(stdout, "Loaded: loaded") {
		t.Errorf("Could not find expected string in status output:\n%s\nstderr:\n%s",
			stdout, stderr)
	}
}
<|endoftext|>