<commit_before>package main

import (
	"os"
	"go/ast"
	"go/parser"
	"io/ioutil"
	"go/token"
	"path"
	"fmt"
)

//-------------------------------------------------------------------------
// ModuleImport
// Contains import information from a single file
//-------------------------------------------------------------------------

type ModuleImport struct {
	Alias  string
	Name   string
	Path   string
}

type ModuleImports []ModuleImport

func NewModuleImports(filename string, decls []ast.Decl) ModuleImports {
	mi := make(ModuleImports, 0, 16)
	mi.appendImports(filename, decls)
	return mi
}

func (mi *ModuleImports) appendImports(filename string, decls []ast.Decl) {
	for _, decl := range decls {
		if gd, ok := decl.(*ast.GenDecl); ok && gd.Tok == token.IMPORT {
			for _, spec := range gd.Specs {
				imp := spec.(*ast.ImportSpec)
				path, alias := pathAndAlias(imp)
				fullpath := fullPathForModule(filename, path)
				mi.appendImport(alias, path, fullpath)
			}
		} else {
			return
		}
	}
}

func (mi *ModuleImports) appendImport(alias, name, path string) {
	v := *mi
	if alias == "_" || alias == "." {
		// TODO: support for modules imported in the current namespace
		return
	}
	if name[0] == '.' {
		// use file path for local packages as name
		name = path
	}

	n := len(v)
	if cap(v) < n+1 {
		s := make(ModuleImports, n, n*2+1)
		copy(s, v)
		v = s
	}

	v = v[0 : n+1]
	v[n] = ModuleImport{alias, name, path}
	*mi = v
}

//-------------------------------------------------------------------------
// DeclFileCache
// Contains cache for top-level declarations of a file. Used in both
// autocompletion and refactoring utilities.
//-------------------------------------------------------------------------

type DeclFileCache struct {
	name  string // file name
	mtime int64  // last modification time

	Data      []byte           // file contents
	File      *ast.File        // an AST tree
	Decls     map[string]*Decl // top-level declarations
	Error     os.Error         // last error
	Modules   ModuleImports    // import information
	FileScope *Scope
}

func NewDeclFileCache(name string) *DeclFileCache {
	f := new(DeclFileCache)
	f.name = name
	return f
}

func (f *DeclFileCache) update() {
	stat, err := os.Stat(f.name)
	if err != nil {
		f.File = nil
		f.Data = nil
		f.Decls = nil
		f.Error = err
		return
	}

	if f.mtime == stat.Mtime_ns {
		return
	}

	f.mtime = stat.Mtime_ns
	f.readFile(f.name)
}

func (f *DeclFileCache) readFile(filename string) {
	f.Data, f.Error = ioutil.ReadFile(f.name)
	if f.Error != nil {
		return
	}

	f.File, f.Error = parser.ParseFile("", f.Data, 0)
	f.FileScope = NewScope(nil)
	f.Modules = NewModuleImports(f.name, f.File.Decls)
	f.Decls = make(map[string]*Decl, len(f.File.Decls))
	for _, decl := range f.File.Decls {
		appendToTopDecls(f.Decls, decl, f.FileScope)
	}
}

func appendToTopDecls(decls map[string]*Decl, decl ast.Decl, scope *Scope) {
	foreachDecl(decl, func(decl ast.Decl, name *ast.Ident, value ast.Expr, valueindex int) {
		d := NewDeclFromAstDecl(name.Name, 0, decl, value, valueindex, scope)
		if d == nil {
			return
		}

		methodof := MethodOf(decl)
		if methodof != "" {
			decl, ok := decls[methodof]
			if ok {
				decl.AddChild(d)
			} else {
				decl = NewDecl(methodof, DECL_METHODS_STUB, scope)
				decls[methodof] = decl
				decl.AddChild(d)
			}
		} else {
			decl, ok := decls[d.Name]
			if ok {
				decl.ExpandOrReplace(d)
			} else {
				decls[d.Name] = d
			}
		}
	})
}

func fullPathForModule(filename, p string) string {
	if p[0] == '.' {
		dir, _ := path.Split(filename)
		return fmt.Sprintf("%s.a", path.Join(dir, p))
	}
	return findGlobalFile(p)
}

func pathAndAlias(imp *ast.ImportSpec) (string, string) {
	path := string(imp.Path.Value)
	alias := ""
	if imp.Name != nil {
		alias = imp.Name.Name
	}
	path = path[1 : len(path)-1]
	return path, alias
}

func findGlobalFile(imp string) string {
	goroot := os.Getenv("GOROOT")
	goarch := os.Getenv("GOARCH")
	goos := os.Getenv("GOOS")

	pkgdir := fmt.Sprintf("%s_%s", goos, goarch)
	pkgfile := fmt.Sprintf("%s.a", imp)

	return path.Join(goroot, "pkg", pkgdir, pkgfile)
}

func packageName(file *ast.File) string {
	if file.Name != nil {
		return file.Name.Name
	}
	return ""
}

//-------------------------------------------------------------------------
// DeclCache
//-------------------------------------------------------------------------

type DeclCache struct {
	cache map[string]*DeclFileCache
}

func NewDeclCache() *DeclCache {
	return &DeclCache{make(map[string]*DeclFileCache)}
}

func (c *DeclCache) Get(filename string) *DeclFileCache {
	f, ok := c.cache[filename]
	if !ok {
		f = NewDeclFileCache(filename)
		c.cache[filename] = f
	}
	f.update()
	return f
}
<commit_msg>Add sync.Mutex to DeclCache, it needs to be thread-safe.<commit_after>package main

import (
	"os"
	"go/ast"
	"go/parser"
	"io/ioutil"
	"go/token"
	"path"
	"fmt"
	"sync"
)

//-------------------------------------------------------------------------
// ModuleImport
// Contains import information from a single file
//-------------------------------------------------------------------------

type ModuleImport struct {
	Alias  string
	Name   string
	Path   string
}

type ModuleImports []ModuleImport

func NewModuleImports(filename string, decls []ast.Decl) ModuleImports {
	mi := make(ModuleImports, 0, 16)
	mi.appendImports(filename, decls)
	return mi
}

func (mi *ModuleImports) appendImports(filename string, decls []ast.Decl) {
	for _, decl := range decls {
		if gd, ok := decl.(*ast.GenDecl); ok && gd.Tok == token.IMPORT {
			for _, spec := range gd.Specs {
				imp := spec.(*ast.ImportSpec)
				path, alias := pathAndAlias(imp)
				fullpath := fullPathForModule(filename, path)
				mi.appendImport(alias, path, fullpath)
			}
		} else {
			return
		}
	}
}

func (mi *ModuleImports) appendImport(alias, name, path string) {
	v := *mi
	if alias == "_" || alias == "." {
		// TODO: support for modules imported in the current namespace
		return
	}
	if name[0] == '.' {
		// use file path for local packages as name
		name = path
	}

	n := len(v)
	if cap(v) < n+1 {
		s := make(ModuleImports, n, n*2+1)
		copy(s, v)
		v = s
	}

	v = v[0 : n+1]
	v[n] = ModuleImport{alias, name, path}
	*mi = v
}

//-------------------------------------------------------------------------
// DeclFileCache
// Contains cache for top-level declarations of a file. Used in both
// autocompletion and refactoring utilities.
//-------------------------------------------------------------------------

type DeclFileCache struct {
	name  string // file name
	mtime int64  // last modification time

	Data      []byte           // file contents
	File      *ast.File        // an AST tree
	Decls     map[string]*Decl // top-level declarations
	Error     os.Error         // last error
	Modules   ModuleImports    // import information
	FileScope *Scope
}

func NewDeclFileCache(name string) *DeclFileCache {
	f := new(DeclFileCache)
	f.name = name
	return f
}

func (f *DeclFileCache) update() {
	stat, err := os.Stat(f.name)
	if err != nil {
		f.File = nil
		f.Data = nil
		f.Decls = nil
		f.Error = err
		return
	}

	if f.mtime == stat.Mtime_ns {
		return
	}

	f.mtime = stat.Mtime_ns
	f.readFile(f.name)
}

func (f *DeclFileCache) readFile(filename string) {
	f.Data, f.Error = ioutil.ReadFile(f.name)
	if f.Error != nil {
		return
	}

	f.File, f.Error = parser.ParseFile("", f.Data, 0)
	f.FileScope = NewScope(nil)
	f.Modules = NewModuleImports(f.name, f.File.Decls)
	f.Decls = make(map[string]*Decl, len(f.File.Decls))
	for _, decl := range f.File.Decls {
		appendToTopDecls(f.Decls, decl, f.FileScope)
	}
}

func appendToTopDecls(decls map[string]*Decl, decl ast.Decl, scope *Scope) {
	foreachDecl(decl, func(decl ast.Decl, name *ast.Ident, value ast.Expr, valueindex int) {
		d := NewDeclFromAstDecl(name.Name, 0, decl, value, valueindex, scope)
		if d == nil {
			return
		}

		methodof := MethodOf(decl)
		if methodof != "" {
			decl, ok := decls[methodof]
			if ok {
				decl.AddChild(d)
			} else {
				decl = NewDecl(methodof, DECL_METHODS_STUB, scope)
				decls[methodof] = decl
				decl.AddChild(d)
			}
		} else {
			decl, ok := decls[d.Name]
			if ok {
				decl.ExpandOrReplace(d)
			} else {
				decls[d.Name] = d
			}
		}
	})
}

func fullPathForModule(filename, p string) string {
	if p[0] == '.' {
		dir, _ := path.Split(filename)
		return fmt.Sprintf("%s.a", path.Join(dir, p))
	}
	return findGlobalFile(p)
}

func pathAndAlias(imp *ast.ImportSpec) (string, string) {
	path := string(imp.Path.Value)
	alias := ""
	if imp.Name != nil {
		alias = imp.Name.Name
	}
	path = path[1 : len(path)-1]
	return path, alias
}

func findGlobalFile(imp string) string {
	goroot := os.Getenv("GOROOT")
	goarch := os.Getenv("GOARCH")
	goos := os.Getenv("GOOS")

	pkgdir := fmt.Sprintf("%s_%s", goos, goarch)
	pkgfile := fmt.Sprintf("%s.a", imp)

	return path.Join(goroot, "pkg", pkgdir, pkgfile)
}

func packageName(file *ast.File) string {
	if file.Name != nil {
		return file.Name.Name
	}
	return ""
}

//-------------------------------------------------------------------------
// DeclCache
//-------------------------------------------------------------------------

type DeclCache struct {
	cache map[string]*DeclFileCache
	sync.Mutex
}

func NewDeclCache() *DeclCache {
	c := new(DeclCache)
	c.cache = make(map[string]*DeclFileCache)
	return c
}

func (c *DeclCache) Get(filename string) *DeclFileCache {
	c.Lock()
	f, ok := c.cache[filename]
	if !ok {
		f = NewDeclFileCache(filename)
		c.cache[filename] = f
	}
	c.Unlock()
	f.update()
	return f
}
<|endoftext|>


<commit_before>package jsonapi;

import (
    . "..";
    . "../extra"
    "net/http"
    "testing"
    "io/ioutil"
);

type Simple struct {
    Id string `jsonapi:"id"`
    Target string
}

func init() {
    ctxf := NewContextFactorySimple();

    api := NewAPI(ctxf);

    no_auth := NewAuthenticatorNone();

    resource_simple := NewResourceRAM(&Simple{});
    resource_simple.Push("1", &Simple{Target:"Potato"});
    resource_simple.Push("Potato", &Simple{Target:"1"});

    api.MountResource("source", resource_simple, no_auth);

    api.MountRelationship("rel", "source", "source", NewRelationshipBehaviorFromFieldToId("Target", Required), no_auth);
    go func() {
        err := http.ListenAndServe(":3030", api);
        if(err != nil) {
            panic(err);
        }
    }()
}

func RunTests(t *testing.T, tests map[string]string) {
    for uri,output := range tests {
        resp, err := http.Get("http://localhost:3030"+uri);
        if err != nil {
            t.Fatalf("HTTP Error: %#v\n", err);
        }
        defer resp.Body.Close()
        body, err := ioutil.ReadAll(resp.Body);
        if(string(body) != output) {
            t.Logf("INTENDED OUTPUT: %s\nACTUAL OUTPUT: %s\nURI: %s\n", output, body, uri);
            t.Fatal();
        }
    }
}

func TestRequestBasics(t *testing.T) {
    tests := map[string]string{
        "/source/1": `{"data":{"attributes":{"Target":"Potato"},"id":"1","links":{"rel":{"linkage":{"type":"source","id":"Potato"},"self":"http://localhost:3030/source/1/links/rel","related":"http://localhost:3030/source/1/rel"}},"type":"source"}}`,

        "/source/1,Potato": `{"data":[{"attributes":{"Target":"Potato"},"id":"1","links":{"rel":{"linkage":{"type":"source","id":"Potato"},"self":"http://localhost:3030/source/1/links/rel","related":"http://localhost:3030/source/1/rel"}},"type":"source"},{"attributes":{"Target":"1"},"id":"Potato","links":{"rel":{"linkage":{"type":"source","id":"1"},"self":"http://localhost:3030/source/Potato/links/rel","related":"http://localhost:3030/source/Potato/rel"}},"type":"source"}]}`,

        "/source/1/rel": `{"data":{"attributes":{"Target":"1"},"id":"Potato","links":{"rel":{"linkage":{"type":"source","id":"1"},"self":"http://localhost:3030/source/Potato/links/rel","related":"http://localhost:3030/source/Potato/rel"}},"type":"source"}}`,

        "/source/1?include=rel":`{"data":{"attributes":{"Target":"Potato"},"id":"1","links":{"rel":{"linkage":{"type":"source","id":"Potato"},"self":"http://localhost:3030/source/1/links/rel","related":"http://localhost:3030/source/1/rel"}},"type":"source"},"included":[{"attributes":{"Target":"1"},"id":"Potato","links":{"rel":{"linkage":{"type":"source","id":"1"},"self":"http://localhost:3030/source/Potato/links/rel","related":"http://localhost:3030/source/Potato/rel"}},"type":"source"}]}`,

        "/source/1/links/rel": `{"data":{"type":"source","id":"Potato"}}`,
    }
    RunTests(t,tests);
}
<commit_msg>Adding small test to make sure primary data is an array even when it is of length 1<commit_after>package jsonapi;

import (
    . "..";
    . "../extra"
    "net/http"
    "testing"
    "io/ioutil"
);

type Simple struct {
    Id string `jsonapi:"id"`
    Target string
}

func init() {
    ctxf := NewContextFactorySimple();

    api := NewAPI(ctxf);

    no_auth := NewAuthenticatorNone();

    resource_simple := NewResourceRAM(&Simple{});
    resource_simple.Push("1", &Simple{Target:"Potato"});
    resource_simple.Push("Potato", &Simple{Target:"1"});

    api.MountResource("source", resource_simple, no_auth);

    api.MountRelationship("rel", "source", "source", NewRelationshipBehaviorFromFieldToId("Target", Required), no_auth);
    go func() {
        err := http.ListenAndServe(":3030", api);
        if(err != nil) {
            panic(err);
        }
    }()
}

func RunTests(t *testing.T, tests map[string]string) {
    for uri,output := range tests {
        resp, err := http.Get("http://localhost:3030"+uri);
        if err != nil {
            t.Fatalf("HTTP Error: %#v\n", err);
        }
        defer resp.Body.Close()
        body, err := ioutil.ReadAll(resp.Body);
        if(string(body) != output) {
            t.Logf("INTENDED OUTPUT: %s\nACTUAL OUTPUT: %s\nURI: %s\n", output, body, uri);
            t.Fatal();
        }
    }
}

func TestRequestBasics(t *testing.T) {
    tests := map[string]string{
        "/source/1": `{"data":{"attributes":{"Target":"Potato"},"id":"1","links":{"rel":{"linkage":{"type":"source","id":"Potato"},"self":"http://localhost:3030/source/1/links/rel","related":"http://localhost:3030/source/1/rel"}},"type":"source"}}`,

        "/source/1,Nonexistant": `{"data":[{"attributes":{"Target":"Potato"},"id":"1","links":{"rel":{"linkage":{"type":"source","id":"Potato"},"self":"http://localhost:3030/source/1/links/rel","related":"http://localhost:3030/source/1/rel"}},"type":"source"}]}`,

        "/source/1,Potato": `{"data":[{"attributes":{"Target":"Potato"},"id":"1","links":{"rel":{"linkage":{"type":"source","id":"Potato"},"self":"http://localhost:3030/source/1/links/rel","related":"http://localhost:3030/source/1/rel"}},"type":"source"},{"attributes":{"Target":"1"},"id":"Potato","links":{"rel":{"linkage":{"type":"source","id":"1"},"self":"http://localhost:3030/source/Potato/links/rel","related":"http://localhost:3030/source/Potato/rel"}},"type":"source"}]}`,

        "/source/1/rel": `{"data":{"attributes":{"Target":"1"},"id":"Potato","links":{"rel":{"linkage":{"type":"source","id":"1"},"self":"http://localhost:3030/source/Potato/links/rel","related":"http://localhost:3030/source/Potato/rel"}},"type":"source"}}`,

        "/source/1?include=rel":`{"data":{"attributes":{"Target":"Potato"},"id":"1","links":{"rel":{"linkage":{"type":"source","id":"Potato"},"self":"http://localhost:3030/source/1/links/rel","related":"http://localhost:3030/source/1/rel"}},"type":"source"},"included":[{"attributes":{"Target":"1"},"id":"Potato","links":{"rel":{"linkage":{"type":"source","id":"1"},"self":"http://localhost:3030/source/Potato/links/rel","related":"http://localhost:3030/source/Potato/rel"}},"type":"source"}]}`,

        "/source/1/links/rel": `{"data":{"type":"source","id":"Potato"}}`,
    }
    RunTests(t,tests);
}
<|endoftext|>


<commit_before>package memkv

import (
	"path/filepath"
	"reflect"
	"testing"
)

var gettests = []struct {
	key   string
	value string
	err   error
	want  KVPair
}{
	{"/db/user", "admin", nil, KVPair{"/db/user", "admin"}},
	{"/db/pass", "foo", nil, KVPair{"/db/pass", "foo"}},
	{"/missing", "", &KeyError{"/missing", ErrNotExist}, KVPair{}},
}

func TestGet(t *testing.T) {
	for _, tt := range gettests {
		s := New()
		if tt.err == nil {
			s.Set(tt.key, tt.value)
		}
		got, err := s.Get(tt.key)
		if got != tt.want || !reflect.DeepEqual(err, tt.err) {
			t.Errorf("Get(%q) = %v, %v, want %v, %v", tt.key, got, err, tt.want, tt.err)
		}
	}
}

var getvtests = []struct {
	key   string
	value string
	err   error
	want  string
}{
	{"/db/user", "admin", nil, "admin"},
	{"/db/pass", "foo", nil, "foo"},
	{"/missing", "", &KeyError{"/missing", ErrNotExist}, ""},
}

func TestGetValue(t *testing.T) {
	for _, tt := range getvtests {
		s := New()
		if tt.err == nil {
			s.Set(tt.key, tt.value)
		}
		got, err := s.GetValue(tt.key)
		if got != tt.want || !reflect.DeepEqual(err, tt.err) {
			t.Errorf("Get(%q) = %v, %v, want %v, %v", tt.key, got, err, tt.want, tt.err)
		}
	}
}

func TestGetValueWithDefault(t *testing.T) {
	want := "defaultValue"
	s := New()
	got, err := s.GetValue("/db/user", "defaultValue")
	if err != nil {
		t.Errorf("Unexpected error", err.Error())
	}
	if got != want {
		t.Errorf("want %v, got %v", want, got)
	}
}

var getalltestinput = map[string]string{
	"/app/db/pass":               "foo",
	"/app/db/user":               "admin",
	"/app/port":                  "443",
	"/app/url":                   "app.example.com",
	"/app/vhosts/host1":          "app.example.com",
	"/app/upstream/host1":        "203.0.113.0.1:8080",
	"/app/upstream/host1/domain": "app.example.com",
	"/app/upstream/host2":        "203.0.113.0.2:8080",
	"/app/upstream/host2/domain": "app.example.com",
}

var getalltests = []struct {
	pattern string
	err     error
	want    []KVPair
}{
	{"/app/db/*", nil,
		[]KVPair{
			KVPair{"/app/db/pass", "foo"},
			KVPair{"/app/db/user", "admin"}}},
	{"/app/*/host1", nil,
		[]KVPair{
			KVPair{"/app/upstream/host1", "203.0.113.0.1:8080"},
			KVPair{"/app/vhosts/host1", "app.example.com"}}},

	{"/app/upstream/*", nil,
		[]KVPair{
			KVPair{"/app/upstream/host1", "203.0.113.0.1:8080"},
			KVPair{"/app/upstream/host2", "203.0.113.0.2:8080"}}},
	{"[]a]", filepath.ErrBadPattern, nil},
	{"/app/missing/*", nil, []KVPair{}},
}

func TestGetAll(t *testing.T) {
	s := New()
	for k, v := range getalltestinput {
		s.Set(k, v)
	}
	for _, tt := range getalltests {
		got, err := s.GetAll(tt.pattern)
		if !reflect.DeepEqual([]KVPair(got), []KVPair(tt.want)) || err != tt.err {
			t.Errorf("GetAll(%q) = %v, %v, want %v, %v", tt.pattern, got, err, tt.want, tt.err)
		}
	}
}

func TestDel(t *testing.T) {
	s := New()
	s.Set("/app/port", "8080")
	want := KVPair{"/app/port", "8080"}
	got, err := s.Get("/app/port")
	if err != nil || got != want {
		t.Errorf("Get(%q) = %v, %v, want %v, %v", "/app/port", got, err, want, true)
	}
	s.Del("/app/port")
	want = KVPair{}
	got, err = s.Get("/app/port")
	if !reflect.DeepEqual(err, &KeyError{"/app/port", ErrNotExist}) || got != want {
		t.Errorf("Get(%q) = %v, %v, want %v, %v", "/app/port", got, err, want, false)
	}
	s.Del("/app/port")
}

func TestPurge(t *testing.T) {
	s := New()
	s.Set("/app/port", "8080")
	want := KVPair{"/app/port", "8080"}
	got, err := s.Get("/app/port")
	if err != nil || got != want {
		t.Errorf("Get(%q) = %v, %v, want %v, %v", "/app/port", got, err, want, true)
	}
	s.Purge()
	want = KVPair{}
	got, err = s.Get("/app/port")
	if !reflect.DeepEqual(err, &KeyError{"/app/port", ErrNotExist}) || got != want {
		t.Errorf("Get(%q) = %v, %v, want %v, %v", "/app/port", got, err, want, false)
	}
	s.Set("/app/port", "8080")
	want = KVPair{"/app/port", "8080"}
	got, err = s.Get("/app/port")
	if err != nil || got != want {
		t.Errorf("Get(%q) = %v, %v, want %v, %v", "/app/port", got, err, want, true)
	}
}

var listTestMap = map[string]string{
	"/deis/database/user":             "user",
	"/deis/database/pass":             "pass",
	"/deis/services/key":              "value",
	"/deis/services/notaservice/foo":  "bar",
	"/deis/services/srv1/node1":       "10.244.1.1:80",
	"/deis/services/srv1/node2":       "10.244.1.2:80",
	"/deis/services/srv1/node3":       "10.244.1.3:80",
	"/deis/services/srv2/node1":       "10.244.2.1:80",
	"/deis/services/srv2/node2":       "10.244.2.2:80",
	"/deis/prefix/node1":              "prefix_node1",
	"/deis/prefix/node2/leafnode":     "prefix_node2",
	"/deis/prefix/node3/leafnode":     "prefix_node3",
	"/deis/prefix_a/node4":            "prefix_a_node4",
	"/deis/prefixb/node5/leafnode":    "prefixb_node5",
	"/deis/dirprefix/node1":           "prefix_node1",
	"/deis/dirprefix/node2/leafnode":  "prefix_node2",
	"/deis/dirprefix/node3/leafnode":  "prefix_node3",
	"/deis/dirprefix_a/node4":         "prefix_a_node4",
	"/deis/dirprefixb/node5/leafnode": "prefixb_node5",
}

func TestList(t *testing.T) {
	s := New()
	for k, v := range listTestMap {
		s.Set(k, v)
	}
	want := []string{"key", "notaservice", "srv1", "srv2"}
	paths := []string{
		"/deis/services",
		"/deis/services/",
	}
	for _, filePath := range paths {
		got := s.List(filePath)
		if !reflect.DeepEqual(got, want) {
			t.Errorf("List(%s) = %v, want %v", filePath, got, want)
		}
	}
}

func TestListForSamePrefix(t *testing.T) {
	s := New()
	for k, v := range listTestMap {
		s.Set(k, v)
	}
	want := []string{"node1", "node2", "node3"}
	paths := []string{
		"/deis/prefix",
		"/deis/prefix/",
	}
	for _, filePath := range paths {
		got := s.List(filePath)
		if !reflect.DeepEqual(got, want) {
			t.Errorf("List(%s) = %v, want %v", filePath, got, want)
		}
	}
}

func TestListForFile(t *testing.T) {
	s := New()
	for k, v := range listTestMap {
		s.Set(k, v)
	}
	want := []string{"key"}
	got := s.List("/deis/services/key")
	if !reflect.DeepEqual(got, want) {
		t.Errorf("List(%s) = %v, want %v", "/deis/services", got, want)
	}
}

func TestListDir(t *testing.T) {
	s := New()
	for k, v := range listTestMap {
		s.Set(k, v)
	}
	want := []string{"notaservice", "srv1", "srv2"}
	paths := []string{
		"/deis/services",
		"/deis/services/",
	}
	for _, filePath := range paths {
		got := s.ListDir(filePath)
		if !reflect.DeepEqual(got, want) {
			t.Errorf("List(%s) = %v, want %v", filePath, got, want)
		}
	}
}

func TestListDirForSamePrefix(t *testing.T) {
	s := New()
	for k, v := range listTestMap {
		s.Set(k, v)
	}
	want := []string{"node2", "node3"}
	paths := []string{
		"/deis/dirprefix",
		"/deis/dirprefix/",
	}
	for _, filePath := range paths {
		got := s.ListDir(filePath)
		if !reflect.DeepEqual(got, want) {
			t.Errorf("List(%s) = %v, want %v", filePath, got, want)
		}
	}
}
<commit_msg>Add tests that demonstrate the issue (fail before patch, pass afterwards)<commit_after>package memkv

import (
	"path/filepath"
	"reflect"
	"testing"
)

var gettests = []struct {
	key   string
	value string
	err   error
	want  KVPair
}{
	{"/db/user", "admin", nil, KVPair{"/db/user", "admin"}},
	{"/db/pass", "foo", nil, KVPair{"/db/pass", "foo"}},
	{"/missing", "", &KeyError{"/missing", ErrNotExist}, KVPair{}},
}

func TestGet(t *testing.T) {
	for _, tt := range gettests {
		s := New()
		if tt.err == nil {
			s.Set(tt.key, tt.value)
		}
		got, err := s.Get(tt.key)
		if got != tt.want || !reflect.DeepEqual(err, tt.err) {
			t.Errorf("Get(%q) = %v, %v, want %v, %v", tt.key, got, err, tt.want, tt.err)
		}
	}
}

var getvtests = []struct {
	key   string
	value string
	err   error
	want  string
}{
	{"/db/user", "admin", nil, "admin"},
	{"/db/pass", "foo", nil, "foo"},
	{"/missing", "", &KeyError{"/missing", ErrNotExist}, ""},
}

func TestGetValue(t *testing.T) {
	for _, tt := range getvtests {
		s := New()
		if tt.err == nil {
			s.Set(tt.key, tt.value)
		}
		got, err := s.GetValue(tt.key)
		if got != tt.want || !reflect.DeepEqual(err, tt.err) {
			t.Errorf("Get(%q) = %v, %v, want %v, %v", tt.key, got, err, tt.want, tt.err)
		}
	}
}

func TestGetValueWithDefault(t *testing.T) {
	want := "defaultValue"
	s := New()
	got, err := s.GetValue("/db/user", "defaultValue")
	if err != nil {
		t.Errorf("Unexpected error", err.Error())
	}
	if got != want {
		t.Errorf("want %v, got %v", want, got)
	}
}

var getalltestinput = map[string]string{
	"/app/db/pass":               "foo",
	"/app/db/user":               "admin",
	"/app/port":                  "443",
	"/app/url":                   "app.example.com",
	"/app/vhosts/host1":          "app.example.com",
	"/app/upstream/host1":        "203.0.113.0.1:8080",
	"/app/upstream/host1/domain": "app.example.com",
	"/app/upstream/host2":        "203.0.113.0.2:8080",
	"/app/upstream/host2/domain": "app.example.com",
}

var getalltests = []struct {
	pattern string
	err     error
	want    []KVPair
}{
	{"/app/db/*", nil,
		[]KVPair{
			KVPair{"/app/db/pass", "foo"},
			KVPair{"/app/db/user", "admin"}}},
	{"/app/*/host1", nil,
		[]KVPair{
			KVPair{"/app/upstream/host1", "203.0.113.0.1:8080"},
			KVPair{"/app/vhosts/host1", "app.example.com"}}},

	{"/app/upstream/*", nil,
		[]KVPair{
			KVPair{"/app/upstream/host1", "203.0.113.0.1:8080"},
			KVPair{"/app/upstream/host2", "203.0.113.0.2:8080"}}},
	{"[]a]", filepath.ErrBadPattern, nil},
	{"/app/missing/*", nil, []KVPair{}},
}

func TestGetAll(t *testing.T) {
	s := New()
	for k, v := range getalltestinput {
		s.Set(k, v)
	}
	for _, tt := range getalltests {
		got, err := s.GetAll(tt.pattern)
		if !reflect.DeepEqual([]KVPair(got), []KVPair(tt.want)) || err != tt.err {
			t.Errorf("GetAll(%q) = %v, %v, want %v, %v", tt.pattern, got, err, tt.want, tt.err)
		}
	}
}

func TestDel(t *testing.T) {
	s := New()
	s.Set("/app/port", "8080")
	want := KVPair{"/app/port", "8080"}
	got, err := s.Get("/app/port")
	if err != nil || got != want {
		t.Errorf("Get(%q) = %v, %v, want %v, %v", "/app/port", got, err, want, true)
	}
	s.Del("/app/port")
	want = KVPair{}
	got, err = s.Get("/app/port")
	if !reflect.DeepEqual(err, &KeyError{"/app/port", ErrNotExist}) || got != want {
		t.Errorf("Get(%q) = %v, %v, want %v, %v", "/app/port", got, err, want, false)
	}
	s.Del("/app/port")
}

func TestPurge(t *testing.T) {
	s := New()
	s.Set("/app/port", "8080")
	want := KVPair{"/app/port", "8080"}
	got, err := s.Get("/app/port")
	if err != nil || got != want {
		t.Errorf("Get(%q) = %v, %v, want %v, %v", "/app/port", got, err, want, true)
	}
	s.Purge()
	want = KVPair{}
	got, err = s.Get("/app/port")
	if !reflect.DeepEqual(err, &KeyError{"/app/port", ErrNotExist}) || got != want {
		t.Errorf("Get(%q) = %v, %v, want %v, %v", "/app/port", got, err, want, false)
	}
	s.Set("/app/port", "8080")
	want = KVPair{"/app/port", "8080"}
	got, err = s.Get("/app/port")
	if err != nil || got != want {
		t.Errorf("Get(%q) = %v, %v, want %v, %v", "/app/port", got, err, want, true)
	}
}

var listTestMap = map[string]string{
	"/deis/database/user":             "user",
	"/deis/database/pass":             "pass",
	"/deis/services/key":              "value",
	"/deis/services/notaservice/foo":  "bar",
	"/deis/services/srv1/node1":       "10.244.1.1:80",
	"/deis/services/srv1/node2":       "10.244.1.2:80",
	"/deis/services/srv1/node3":       "10.244.1.3:80",
	"/deis/services/srv2/node1":       "10.244.2.1:80",
	"/deis/services/srv2/node2":       "10.244.2.2:80",
	"/deis/prefix/node1":              "prefix_node1",
	"/deis/prefix/node2/leafnode":     "prefix_node2",
	"/deis/prefix/node3/leafnode":     "prefix_node3",
	"/deis/prefix_a/node4":            "prefix_a_node4",
	"/deis/prefixb/node5/leafnode":    "prefixb_node5",
	"/deis/dirprefix/node1":           "prefix_node1",
	"/deis/dirprefix/node2/leafnode":  "prefix_node2",
	"/deis/dirprefix/node3/leafnode":  "prefix_node3",
	"/deis/dirprefix_a/node4":         "prefix_a_node4",
	"/deis/dirprefixb/node5/leafnode": "prefixb_node5",
}

func TestList(t *testing.T) {
	s := New()
	for k, v := range listTestMap {
		s.Set(k, v)
	}
	want := []string{"key", "notaservice", "srv1", "srv2"}
	paths := []string{
		"/deis/services",
		"/deis/services/",
	}
	for _, filePath := range paths {
		got := s.List(filePath)
		if !reflect.DeepEqual(got, want) {
			t.Errorf("List(%s) = %v, want %v", filePath, got, want)
		}
	}
}

func TestListForSamePrefix(t *testing.T) {
	s := New()
	for k, v := range listTestMap {
		s.Set(k, v)
	}
	want := []string{"node1", "node2", "node3"}
	paths := []string{
		"/deis/prefix",
		"/deis/prefix/",
	}
	for _, filePath := range paths {
		got := s.List(filePath)
		if !reflect.DeepEqual(got, want) {
			t.Errorf("List(%s) = %v, want %v", filePath, got, want)
		}
	}
}

func TestListForFile(t *testing.T) {
	s := New()
	for k, v := range listTestMap {
		s.Set(k, v)
	}
	want := []string{"key"}
	got := s.List("/deis/services/key")
	if !reflect.DeepEqual(got, want) {
		t.Errorf("List(%s) = %v, want %v", "/deis/services", got, want)
	}
}

func TestListEmptyChildrenTrailingSlash(t *testing.T) {
	s := New()
	s.Set("/top/first", "")
	s.Set("/top/second", "")
	s.Set("/misc", "")
	want := []string{}
	paths := []string{"/top/first/", "/top/second/"}
	for _, filePath := range paths {
		got := s.List(filePath)
		if !reflect.DeepEqual(got, want) {
			t.Errorf("List(%s) = %v, want %v", filePath, got, want)
		}
	}
}

func TestListEmptyChildren(t *testing.T) {
	s := New()
	s.Set("/top/first", "")
	s.Set("/top/second", "")
	s.Set("/misc", "")

	first := s.List("/top/first")
	if !reflect.DeepEqual(first, []string{"first"}) {
		t.Errorf("List(/top/first) = %v, want [first]", first)
	}

	second := s.List("/top/second")
	if !reflect.DeepEqual(second, []string{"second"}) {
		t.Errorf("List(/top/second) = %v, want [second]", second)
	}
}

func TestListDir(t *testing.T) {
	s := New()
	for k, v := range listTestMap {
		s.Set(k, v)
	}
	want := []string{"notaservice", "srv1", "srv2"}
	paths := []string{
		"/deis/services",
		"/deis/services/",
	}
	for _, filePath := range paths {
		got := s.ListDir(filePath)
		if !reflect.DeepEqual(got, want) {
			t.Errorf("List(%s) = %v, want %v", filePath, got, want)
		}
	}
}

func TestListDirForSamePrefix(t *testing.T) {
	s := New()
	for k, v := range listTestMap {
		s.Set(k, v)
	}
	want := []string{"node2", "node3"}
	paths := []string{
		"/deis/dirprefix",
		"/deis/dirprefix/",
	}
	for _, filePath := range paths {
		got := s.ListDir(filePath)
		if !reflect.DeepEqual(got, want) {
			t.Errorf("List(%s) = %v, want %v", filePath, got, want)
		}
	}
}
<|endoftext|>


<commit_before>package sharefile

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/http/httputil"
	"strconv"
	"strings"
)

type Login struct {
	Credentials
}

type Credentials interface {
	Account() Account
	Do(*http.Request) (*http.Response, error)
}

func (login Login) doPost(ctx context.Context, url string, send, recv interface{}) error {
	body, err := toBody(send)
	if err != nil {
		return fmt.Errorf("Failed to serialize body: %v", err)
	}
	req, err := http.NewRequest("POST", url, body)
	if err != nil {
		return fmt.Errorf("Failed to create post request: %v", err)
	}
	req.Header.Add("Content-Type", "application/json")
	return login.do(ctx, req, recv)
}

func (login Login) doPatch(ctx context.Context, url string, send, recv interface{}) error {
	body, err := toBody(send)
	if err != nil {
		return fmt.Errorf("Failed to serialize body: %v", err)
	}
	req, err := http.NewRequest("PATCH", url, body)
	if err != nil {
		return fmt.Errorf("Failed to create patch request: %v", err)
	}
	req.Header.Add("Content-Type", "application/json")
	return login.do(ctx, req, recv)
}

func (login *Login) doDelete(ctx context.Context, url string) error {
	req, err := http.NewRequest("DELETE", url, nil)
	if err != nil {
		return fmt.Errorf("Failed to create delete request: %v", err)
	}
	err = login.do(ctx, req, nil)
	// no no no
	if strings.HasPrefix(err.Error(), strconv.Itoa(http.StatusAccepted)) {
		return nil
	}
	return err
}

func toBody(send interface{}) (io.Reader, error) {
	var body io.Reader
	if send != nil {
		b, err := json.Marshal(send)
		if err != nil {
			return nil, err
		}
		body = bytes.NewReader(b)
	}
	return body, nil
}

func (login *Login) doGet(ctx context.Context, url string, recv interface{}) error {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return err
	}
	return login.do(ctx, req, recv)
}

func (login *Login) do(ctx context.Context, req *http.Request, recv interface{}) error {
	// log.dbg this through context
	b, _ := httputil.DumpRequestOut(req, req.Method != "GET")
	fmt.Println(string(b))

	resp, err := login.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	b, _ = httputil.DumpResponse(resp, true)
	fmt.Println(string(b))

	if resp.StatusCode != http.StatusOK {
		return errors.New(resp.Status)
	}
	if recv != nil {
		err = json.NewDecoder(resp.Body).Decode(recv)
		if err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>remove http prints so refresh prints have time<commit_after>package sharefile

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"strconv"
	"strings"
)

type Login struct {
	Credentials
}

type Credentials interface {
	Account() Account
	Do(*http.Request) (*http.Response, error)
}

func (login Login) doPost(ctx context.Context, url string, send, recv interface{}) error {
	body, err := toBody(send)
	if err != nil {
		return fmt.Errorf("Failed to serialize body: %v", err)
	}
	req, err := http.NewRequest("POST", url, body)
	if err != nil {
		return fmt.Errorf("Failed to create post request: %v", err)
	}
	req.Header.Add("Content-Type", "application/json")
	return login.do(ctx, req, recv)
}

func (login Login) doPatch(ctx context.Context, url string, send, recv interface{}) error {
	body, err := toBody(send)
	if err != nil {
		return fmt.Errorf("Failed to serialize body: %v", err)
	}
	req, err := http.NewRequest("PATCH", url, body)
	if err != nil {
		return fmt.Errorf("Failed to create patch request: %v", err)
	}
	req.Header.Add("Content-Type", "application/json")
	return login.do(ctx, req, recv)
}

func (login *Login) doDelete(ctx context.Context, url string) error {
	req, err := http.NewRequest("DELETE", url, nil)
	if err != nil {
		return fmt.Errorf("Failed to create delete request: %v", err)
	}
	err = login.do(ctx, req, nil)
	// no no no
	if strings.HasPrefix(err.Error(), strconv.Itoa(http.StatusNoContent)) {
		return nil
	}
	return err
}

func toBody(send interface{}) (io.Reader, error) {
	var body io.Reader
	if send != nil {
		b, err := json.Marshal(send)
		if err != nil {
			return nil, err
		}
		body = bytes.NewReader(b)
	}
	return body, nil
}

func (login *Login) doGet(ctx context.Context, url string, recv interface{}) error {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return err
	}
	return login.do(ctx, req, recv)
}

func (login *Login) do(ctx context.Context, req *http.Request, recv interface{}) error {
	// log.dbg this through context
	// b, _ := httputil.DumpRequestOut(req, req.Method != "GET")
	// fmt.Println(string(b))

	resp, err := login.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	// b, _ = httputil.DumpResponse(resp, true)
	// fmt.Println(string(b))

	if resp.StatusCode != http.StatusOK {
		return errors.New(resp.Status)
	}
	if recv != nil {
		err = json.NewDecoder(resp.Body).Decode(recv)
		if err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package fs

// Version of rclone
var Version = "v1.50.0"
<commit_msg>Start v1.50.0-DEV development<commit_after>package fs

// Version of rclone
var Version = "v1.50.0-DEV"
<|endoftext|>


<commit_before>// Package pushpackage creates push packages for website push notifications.
package pushpackage

import (
	"archive/zip"
	"bytes"
	"encoding/json"
	"io"
	"log"
	"path"
)

// New push package.
func New(buf io.Writer, website *Website, iconset IconSet) error {
	z := zip.NewWriter(buf)

	// manifest is a map of relative file paths to their SHA checksums
	manifest := make(map[string]string, len(iconset)+1)

	b, err := json.Marshal(website)
	if err != nil {
		return err
	}
	r := bytes.NewReader(b)

	zf, err := z.Create("website.json")
	if err != nil {
		return err
	}
	checksum, err := copyAndChecksum(zf, r)
	manifest["website.json"] = checksum

	for _, icon := range iconset {
		// NOTE: only forward slashes are allowed in zip files
		// (therefore using path rather than filepath)
		name := path.Join(iconDirectory, icon.Name)

		zf, err := z.Create(name)
		if err != nil {
			return err
		}
		checksum, err := copyAndChecksum(zf, icon.Reader)
		manifest[name] = checksum
	}

	log.Println(manifest)

	manifestBytes, err := json.Marshal(manifest)
	if err != nil {
		return err
	}
	zf, err = z.Create("manifest.json")
	if err != nil {
		return err
	}
	zf.Write(manifestBytes)

	// TODO: sign manifest.json with PKCS #7
	// and add signature to the zip file
	zf, err = z.Create("signature")
	if err != nil {
		return err
	}
	zf.Write([]byte(``))

	return z.Close()
}
<commit_msg>testing with manually created signature<commit_after>// Package pushpackage creates push packages for website push notifications.
package pushpackage

import (
	"archive/zip"
	"bytes"
	"encoding/json"
	"io"
	"log"
	"os"
	"path"
)

// New push package.
func New(buf io.Writer, website *Website, iconset IconSet) error {
	z := zip.NewWriter(buf)

	// manifest is a map of relative file paths to their SHA checksums
	manifest := make(map[string]string, len(iconset)+1)

	b, err := json.Marshal(website)
	if err != nil {
		return err
	}
	r := bytes.NewReader(b)

	zf, err := z.Create("website.json")
	if err != nil {
		return err
	}
	checksum, err := copyAndChecksum(zf, r)
	manifest["website.json"] = checksum

	for _, icon := range iconset {
		// NOTE: only forward slashes are allowed in zip files
		// (therefore using path rather than filepath)
		name := path.Join(iconDirectory, icon.Name)

		zf, err := z.Create(name)
		if err != nil {
			return err
		}
		checksum, err := copyAndChecksum(zf, icon.Reader)
		manifest[name] = checksum
	}

	manifestBytes, err := json.Marshal(manifest)
	if err != nil {
		return err
	}

	log.Println(string(manifestBytes))

	zf, err = z.Create("manifest.json")
	if err != nil {
		return err
	}
	zf.Write(manifestBytes)

	// TODO: sign manifest.json with PKCS #7
	// and add signature to the zip file
	zf, err = z.Create("signature")
	if err != nil {
		return err
	}
	sig, err := os.Open("./signature")
	if err != nil {
		return err
	}
	defer sig.Close()
	io.Copy(zf, sig)
	// zf.Write([]byte(``))

	return z.Close()
}
<|endoftext|>


<commit_before>package plugins

import (
	"ircclient"
	"strings"
	"log"
	"fmt"
)

type ListPlugins struct {
	ic *ircclient.IRCClient
}

func (lp *ListPlugins) Register(ic *ircclient.IRCClient) {
	lp.ic = ic
	ic.RegisterCommandHandler("listplugins", 0, 0, lp)
}

func (lp ListPlugins) String() string {
	return "listplugins"
}

func (lp ListPlugins) Info() string {
	return "Lists all currently registered Plugins"
}

func (lp ListPlugins) ProcessLine(msg *ircclient.IRCMessage) {
	return
}

/**
 * the array-foo makes it easy to leave out the last ", "
 * because strings.Join() does that for us
 **/
func (lp ListPlugins) ProcessCommand(cmd *ircclient.IRCCommand) {
	a := make([]string, 0)
	for plug := range lp.ic.IterPlugins() {
		a = append(a, plug.String())
	}

	// channel vs. query
	var ret_targ string
	if cmd.Target[0] == '#' {
		ret_targ = cmd.Target
	} else {
		ret_targ = cmd.Source
	}
	ret := fmt.Sprintf("PRIVMSG %s :%s", ret_targ, strings.Join(a, ", "))
	log.Println("listplugins output: " + ret)
	lp.ic.SendLine(ret)
}

func (lp ListPlugins) Unregister() {
	// nothing to do here
}
<commit_msg>Fix listplugins<commit_after>package plugins

import (
	"ircclient"
	"strings"
)

type ListPlugins struct {
	ic *ircclient.IRCClient
}

func (lp *ListPlugins) Register(ic *ircclient.IRCClient) {
	lp.ic = ic
	ic.RegisterCommandHandler("listplugins", 0, 0, lp)
}

func (lp *ListPlugins) String() string {
	return "listplugins"
}

func (lp *ListPlugins) Info() string {
	return "Lists all currently registered Plugins"
}

func (lp *ListPlugins) ProcessLine(msg *ircclient.IRCMessage) {
	return
}

/**
 * the array-foo makes it easy to leave out the last ", "
 * because strings.Join() does that for us
 **/
func (lp *ListPlugins) ProcessCommand(cmd *ircclient.IRCCommand) {
	a := make([]string, 0)
	for plug := range lp.ic.IterPlugins() {
		a = append(a, plug.String())
	}

	lp.ic.Reply(cmd, strings.Join(a, ", "))
}

func (lp *ListPlugins) Unregister() {
	// nothing to do here
}
<|endoftext|>


<commit_before>package types

import (
	"fmt"
	"go/ast"
	"go/token"
	"regexp"
	"strings"

	goast "go/ast"

	"strconv"

	"github.com/elliotchance/c2go/program"
	"github.com/elliotchance/c2go/util"
)

// GetArrayTypeAndSize returns the size and type of a fixed array. If the type
// is not an array with a fixed size then the type return will be an empty
// string, and the size will be -1.
func GetArrayTypeAndSize(s string) (string, int) {
	match := regexp.MustCompile(`(.*) \[(\d+)\]`).FindStringSubmatch(s)
	if len(match) > 0 {
		return match[1], util.Atoi(match[2])
	}

	return "", -1
}

func CastExpr(p *program.Program, expr ast.Expr, fromType, toType string) (ast.Expr, error) {
	// Let's assume that anything can be converted to a void pointer.
	if toType == "void *" {
		return expr, nil
	}

	fromType, err := ResolveType(p, fromType)
	if err != nil {
		return expr, err
	}

	toType, err = ResolveType(p, toType)
	if err != nil {
		return expr, err
	}

	if fromType == "null" && toType == "[][]byte" {
		return util.NewNil(), nil
	}

	if fromType == "null" && toType == "float64" {
		return util.NewStringLit("0.0"), nil
	}

	if fromType == "null" && toType == "bool" {
		return util.NewIdent("false"), nil
	}

	// FIXME: This is a hack to avoid casting in some situations.
	if fromType == "" || toType == "" {
		return expr, nil
	}

	if fromType == "null" && toType == "[]byte" {
		return util.NewNil(), nil
	}

	// This if for linux.
	if fromType == "*_IO_FILE" && toType == "*noarch.File" {
		return expr, nil
	}

	if fromType == toType {
		return expr, nil
	}

	// Compatible integer types
	types := []string{
		// Integer types
		"byte",
		"int", "int16", "int32", "int64",
		"uint16", "uint32", "uint64",

		// Floating-point types.
		"float32", "float64",

		// Known aliases
		"__uint16_t", "size_t",

		// Darwin specific
		"__darwin_ct_rune_t", "darwin.Darwin_ct_rune_t",
	}
	for _, v := range types {
		if fromType == v && toType == "bool" {
			return &goast.BinaryExpr{
				X:  expr,
				Op: token.NEQ,
				Y:  util.NewIntLit(0),
			}, nil
		}
	}

	// In the forms of:
	// - `string` -> `[]byte`
	// - `string` -> `char *[13]`
	match1 := regexp.MustCompile(`\[\]byte`).FindStringSubmatch(toType)
	match2 := regexp.MustCompile(`char \*\[(\d+)\]`).FindStringSubmatch(toType)
	if fromType == "string" && (len(match1) > 0 || len(match2) > 0) {
		// Construct a byte array from "first":
		//
		//     var str []byte = []byte{'f','i','r','s','t'}

		value := &goast.CompositeLit{
			Type: &goast.ArrayType{
				Elt: util.NewTypeIdent("byte"),
			},
			Elts: []goast.Expr{},
		}

		strValue, err := strconv.Unquote(expr.(*goast.BasicLit).Value)
		if err != nil {
			panic(fmt.Sprintf("Failed to Unquote %s\n", expr.(*goast.BasicLit).Value))
		}

		for _, c := range []byte(strValue) {
			value.Elts = append(value.Elts, &goast.BasicLit{
				Kind:  token.CHAR,
				Value: fmt.Sprintf("%q", c),
			})
		}

		value.Elts = append(value.Elts, util.NewIntLit(0))

		return value, nil
	}

	// In the forms of:
	// - `[7]byte` -> `string`
	// - `char *[12]` -> `string`
	match1 = regexp.MustCompile(`\[(\d+)\]byte`).FindStringSubmatch(fromType)
	match2 = regexp.MustCompile(`char \*\[(\d+)\]`).FindStringSubmatch(fromType)
	if (len(match1) > 0 || len(match2) > 0) && toType == "string" {
		size := 0
		if len(match1) > 0 {
			size = util.Atoi(match1[1])
		} else {
			size = util.Atoi(match2[1])
		}

		// The following code builds this:
		//
		//     string(expr[:size - 1])
		//
		return util.NewCallExpr(
			"string",
			&goast.SliceExpr{
				X:    expr,
				High: util.NewIntLit(size - 1),
			},
		), nil
	}

	// Anything that is a pointer can be compared to nil
	if fromType[0] == '*' && toType == "bool" {
		return &goast.BinaryExpr{
			X:  expr,
			Op: token.NEQ,
			Y:  util.NewNil(),
		}, nil
	}

	if fromType == "[]byte" && toType == "bool" {
		return util.NewUnaryExpr(
			token.NOT, util.NewCallExpr("noarch.CStringIsNull", expr),
		), nil
	}

	if fromType == "int" && toType == "*int" {
		return util.NewNil(), nil
	}
	if fromType == "int" && toType == "*byte" {
		return &goast.BasicLit{
			Kind:  token.STRING,
			Value: `""`,
		}, nil
	}

	if fromType == "_Bool" && toType == "bool" {
		return expr, nil
	}

	if util.InStrings(fromType, types) && util.InStrings(toType, types) {
		return util.NewCallExpr(toType, expr), nil
	}

	p.AddImport("github.com/elliotchance/c2go/noarch")

	leftName := fromType
	rightName := toType

	if strings.Index(leftName, ".") != -1 {
		parts := strings.Split(leftName, ".")
		leftName = parts[len(parts)-1]
	}
	if strings.Index(rightName, ".") != -1 {
		parts := strings.Split(rightName, ".")
		rightName = parts[len(parts)-1]
	}

	functionName := fmt.Sprintf("noarch.%sTo%s",
		util.GetExportedName(leftName), util.GetExportedName(rightName))

	return util.NewCallExpr(functionName, expr), nil
}

func IsNullExpr(n goast.Expr) bool {
	if p1, ok := n.(*goast.ParenExpr); ok {
		if p2, ok := p1.X.(*goast.BasicLit); ok && p2.Value == "0" {
			return true
		}
	}

	return false
}
<commit_msg>Use `NewStringLit` instead of `BasicLit`<commit_after>package types

import (
	"fmt"
	"go/ast"
	"go/token"
	"regexp"
	"strings"

	goast "go/ast"

	"strconv"

	"github.com/elliotchance/c2go/program"
	"github.com/elliotchance/c2go/util"
)

// GetArrayTypeAndSize returns the size and type of a fixed array. If the type
// is not an array with a fixed size then the type return will be an empty
// string, and the size will be -1.
func GetArrayTypeAndSize(s string) (string, int) {
	match := regexp.MustCompile(`(.*) \[(\d+)\]`).FindStringSubmatch(s)
	if len(match) > 0 {
		return match[1], util.Atoi(match[2])
	}

	return "", -1
}

func CastExpr(p *program.Program, expr ast.Expr, fromType, toType string) (ast.Expr, error) {
	// Let's assume that anything can be converted to a void pointer.
	if toType == "void *" {
		return expr, nil
	}

	fromType, err := ResolveType(p, fromType)
	if err != nil {
		return expr, err
	}

	toType, err = ResolveType(p, toType)
	if err != nil {
		return expr, err
	}

	if fromType == "null" && toType == "[][]byte" {
		return util.NewNil(), nil
	}

	if fromType == "null" && toType == "float64" {
		return util.NewStringLit("0.0"), nil
	}

	if fromType == "null" && toType == "bool" {
		return util.NewIdent("false"), nil
	}

	// FIXME: This is a hack to avoid casting in some situations.
	if fromType == "" || toType == "" {
		return expr, nil
	}

	if fromType == "null" && toType == "[]byte" {
		return util.NewNil(), nil
	}

	// This if for linux.
	if fromType == "*_IO_FILE" && toType == "*noarch.File" {
		return expr, nil
	}

	if fromType == toType {
		return expr, nil
	}

	// Compatible integer types
	types := []string{
		// Integer types
		"byte",
		"int", "int16", "int32", "int64",
		"uint16", "uint32", "uint64",

		// Floating-point types.
		"float32", "float64",

		// Known aliases
		"__uint16_t", "size_t",

		// Darwin specific
		"__darwin_ct_rune_t", "darwin.Darwin_ct_rune_t",
	}
	for _, v := range types {
		if fromType == v && toType == "bool" {
			return &goast.BinaryExpr{
				X:  expr,
				Op: token.NEQ,
				Y:  util.NewIntLit(0),
			}, nil
		}
	}

	// In the forms of:
	// - `string` -> `[]byte`
	// - `string` -> `char *[13]`
	match1 := regexp.MustCompile(`\[\]byte`).FindStringSubmatch(toType)
	match2 := regexp.MustCompile(`char \*\[(\d+)\]`).FindStringSubmatch(toType)
	if fromType == "string" && (len(match1) > 0 || len(match2) > 0) {
		// Construct a byte array from "first":
		//
		//     var str []byte = []byte{'f','i','r','s','t'}

		value := &goast.CompositeLit{
			Type: &goast.ArrayType{
				Elt: util.NewTypeIdent("byte"),
			},
			Elts: []goast.Expr{},
		}

		strValue, err := strconv.Unquote(expr.(*goast.BasicLit).Value)
		if err != nil {
			panic(fmt.Sprintf("Failed to Unquote %s\n", expr.(*goast.BasicLit).Value))
		}

		for _, c := range []byte(strValue) {
			value.Elts = append(value.Elts, &goast.BasicLit{
				Kind:  token.CHAR,
				Value: fmt.Sprintf("%q", c),
			})
		}

		value.Elts = append(value.Elts, util.NewIntLit(0))

		return value, nil
	}

	// In the forms of:
	// - `[7]byte` -> `string`
	// - `char *[12]` -> `string`
	match1 = regexp.MustCompile(`\[(\d+)\]byte`).FindStringSubmatch(fromType)
	match2 = regexp.MustCompile(`char \*\[(\d+)\]`).FindStringSubmatch(fromType)
	if (len(match1) > 0 || len(match2) > 0) && toType == "string" {
		size := 0
		if len(match1) > 0 {
			size = util.Atoi(match1[1])
		} else {
			size = util.Atoi(match2[1])
		}

		// The following code builds this:
		//
		//     string(expr[:size - 1])
		//
		return util.NewCallExpr(
			"string",
			&goast.SliceExpr{
				X:    expr,
				High: util.NewIntLit(size - 1),
			},
		), nil
	}

	// Anything that is a pointer can be compared to nil
	if fromType[0] == '*' && toType == "bool" {
		return &goast.BinaryExpr{
			X:  expr,
			Op: token.NEQ,
			Y:  util.NewNil(),
		}, nil
	}

	if fromType == "[]byte" && toType == "bool" {
		return util.NewUnaryExpr(
			token.NOT, util.NewCallExpr("noarch.CStringIsNull", expr),
		), nil
	}

	if fromType == "int" && toType == "*int" {
		return util.NewNil(), nil
	}
	if fromType == "int" && toType == "*byte" {
		return util.NewStringLit(`""`), nil
	}

	if fromType == "_Bool" && toType == "bool" {
		return expr, nil
	}

	if util.InStrings(fromType, types) && util.InStrings(toType, types) {
		return util.NewCallExpr(toType, expr), nil
	}

	p.AddImport("github.com/elliotchance/c2go/noarch")

	leftName := fromType
	rightName := toType

	if strings.Index(leftName, ".") != -1 {
		parts := strings.Split(leftName, ".")
		leftName = parts[len(parts)-1]
	}
	if strings.Index(rightName, ".") != -1 {
		parts := strings.Split(rightName, ".")
		rightName = parts[len(parts)-1]
	}

	functionName := fmt.Sprintf("noarch.%sTo%s",
		util.GetExportedName(leftName), util.GetExportedName(rightName))

	return util.NewCallExpr(functionName, expr), nil
}

func IsNullExpr(n goast.Expr) bool {
	if p1, ok := n.(*goast.ParenExpr); ok {
		if p2, ok := p1.X.(*goast.BasicLit); ok && p2.Value == "0" {
			return true
		}
	}

	return false
}
<|endoftext|>


<commit_before>package redlot

import (
	"errors"
	"strconv"
	"time"

	"github.com/syndtr/goleveldb/leveldb"
	"github.com/syndtr/goleveldb/leveldb/util"
)

func encodeKvKey(key []byte) (buf []byte) {
	buf = append(buf, typeKV)
	buf = append(buf, key...)
	return
}

func decodeKvKey(buf []byte) (key []byte) {
	if len(buf) < 2 {
		return []byte{}
	}
	return buf[1:]
}

// Get a value by a key.
// Args: key string
func Get(args [][]byte) (interface{}, error) {
	if len(args) < 1 {
		return "", errNosArgs
	}

	v, err := db.Get(encodeKvKey(args[0]), nil)
	return string(v), err
}

// Set a value by a key.
// Args: key string, value any
func Set(args [][]byte) (interface{}, error) {
	if len(args) < 2 {
		return nil, errNosArgs
	}

	// fmt.Printf("SET %s %s\n", args[0], args[1])
	return nil, db.Put(encodeKvKey(args[0]), args[1], nil)
}

// Del will delete a value by a key.
// Args: key string
func Del(args [][]byte) (interface{}, error) {
	if len(args) < 1 {
		return nil, errNosArgs
	}
	return nil, db.Delete(encodeKvKey(args[0]), nil)
}

// Exists will check key is exists.
// Args: key string
func Exists(args [][]byte) (interface{}, error) {
	if len(args) < 1 {
		return int64(-1), errNosArgs
	}

	ret, err := db.Has(encodeKvKey(args[0]), nil)
	if ret {
		return int64(1), err
	}
	return int64(0), err
}

// Expire the key after timeout.
// Args: key string, seconds int
func Expire(args [][]byte) (interface{}, error) {
	if len(args) < 2 {
		return nil, errNosArgs
	}

	key := encodeKvKey(args[0])
	has, _ := db.Has(key, nil)
	if has {
		ttl := strToInt64(string(args[1]))
		if ttl < 1 {
			return nil, errors.New("TTL must > 0, you set to " + string(args[1]))
		}
		bs := uint64ToBytes(uint64(time.Now().UTC().Unix() + ttl))
		if meta.Put(key, bs, nil) == nil {
			return int64(1), nil
		}
	}
	return int64(0), nil
}

// Setx will set a value by the key and expire it after timeout.
// Args: key string, value any, seconds int
func Setx(args [][]byte) (interface{}, error) {
	if len(args) < 3 {
		return nil, errNosArgs
	}
	key := encodeKvKey(args[0])

	ttl := strToInt64(string(args[2]))
	if ttl < 1 {
		return nil, errors.New("TTL must > 0, you set to " + string(args[2]))
	}
	bs := uint64ToBytes(uint64(time.Now().UTC().Unix() + ttl))
	meta.Put(key, bs, nil)

	return nil, db.Put(key, args[1], nil)
}

// TTL will return the lifetime of the key.
// Args: key string
func TTL(args [][]byte) (interface{}, error) {
	if len(args) < 1 {
		return int64(-1), errNosArgs
	}

	key := encodeKvKey(args[0])
	b, _ := meta.Get(key, nil)
	if len(b) < 1 {
		return int64(-1), nil
	}
	ttl := int64(bytesToUint64(b)) - time.Now().UTC().Unix()
	if ttl < 0 {
		ttl = -1
		meta.Delete(key, nil)
		db.Delete(key, nil)
	}
	return ttl, nil
}

func keys(args [][]byte, reverse bool) ([]string, error) {
	if len(args) < 3 {
		return []string{}, errNosArgs
	}

	ks := encodeKvKey(args[0])
	ke := encodeKvKey(args[1])
	limit, _ := strconv.Atoi(string(args[2]))

	var keys []string
	iter := db.NewIterator(&util.Range{Start: ks, Limit: ke}, nil)
	if reverse {
		iter.Seek(ke)
		for iter.Prev() {
			k := decodeKvKey(iter.Key())
			keys = append(keys, string(k))
			limit--
			if limit == 0 {
				break
			}
		}
	} else {
		for iter.Next() {
			k := decodeKvKey(iter.Key())
			keys = append(keys, string(k))
			limit--
			if limit == 0 {
				break
			}
		}
	}
	iter.Release()
	err := iter.Error()
	return keys, err
}

// Keys will list keys in the range.
// Args: start_key string, end_key string, limit_number int
func Keys(args [][]byte) ([]string, error) {
	return keys(args, false)
}
func scan(args [][]byte, reverse bool) ([]string, error) {
	if len(args) < 3 {
		return []string{}, errNosArgs
	}

	ks := encodeKvKey(args[0])
	ke := encodeKvKey(args[1])
	limit, _ := strconv.Atoi(string(args[2]))

	var ret []string
	iter := db.NewIterator(&util.Range{Start: ks, Limit: ke}, nil)
	if reverse {
		iter.Seek(ke)
		for iter.Prev() {
			k := decodeKvKey(iter.Key())
			ret = append(ret, string(k))
			ret = append(ret, string(iter.Value()))
			limit--
			if limit == 0 {
				break
			}
		}
	} else {
		for iter.Next() {
			k := decodeKvKey(iter.Key())
			ret = append(ret, string(k))
			ret = append(ret, string(iter.Value()))
			limit--
			if limit == 0 {
				break
			}
		}
	}
	iter.Release()
	err := iter.Error()
	return ret, err
}

// Scan will list KV pair that keys in the range.
// Args: start_key string, end_key string, limit_number int
func Scan(args [][]byte) ([]string, error) {
	return scan(args, false)
}

// Rscan will reverse list KV pair that keys in the range.
// Args: start_key string, end_key string, limit_number int
func Rscan(args [][]byte) ([]string, error) {
	return scan(args, true)
}

// MultiGet wil batch read data from db.
func MultiGet(args [][]byte) (r []string, err error) {
	if len(args) < 1 {
		return []string{}, errNosArgs
	}
	for _, key := range args {
		v, _ := db.Get(encodeKvKey(key), nil)
		r = append(r, string(key))
		r = append(r, string(v))
	}
	return
}
<commit_msg>Add Rkeys method.<commit_after>package redlot

import (
	"errors"
	"strconv"
	"time"

	"github.com/syndtr/goleveldb/leveldb"
	"github.com/syndtr/goleveldb/leveldb/util"
)

func encodeKvKey(key []byte) (buf []byte) {
	buf = append(buf, typeKV)
	buf = append(buf, key...)
	return
}

func decodeKvKey(buf []byte) (key []byte) {
	if len(buf) < 2 {
		return []byte{}
	}
	return buf[1:]
}

// Get a value by a key.
// Args: key string
func Get(args [][]byte) (interface{}, error) {
	if len(args) < 1 {
		return "", errNosArgs
	}

	v, err := db.Get(encodeKvKey(args[0]), nil)
	return string(v), err
}

// Set a value by a key.
// Args: key string, value any
func Set(args [][]byte) (interface{}, error) {
	if len(args) < 2 {
		return nil, errNosArgs
	}

	// fmt.Printf("SET %s %s\n", args[0], args[1])
	return nil, db.Put(encodeKvKey(args[0]), args[1], nil)
}

// Del will delete a value by a key.
// Args: key string
func Del(args [][]byte) (interface{}, error) {
	if len(args) < 1 {
		return nil, errNosArgs
	}
	return nil, db.Delete(encodeKvKey(args[0]), nil)
}

// Exists will check key is exists.
// Args: key string
func Exists(args [][]byte) (interface{}, error) {
	if len(args) < 1 {
		return int64(-1), errNosArgs
	}

	ret, err := db.Has(encodeKvKey(args[0]), nil)
	if ret {
		return int64(1), err
	}
	return int64(0), err
}

// Expire the key after timeout.
// Args: key string, seconds int
func Expire(args [][]byte) (interface{}, error) {
	if len(args) < 2 {
		return nil, errNosArgs
	}

	key := encodeKvKey(args[0])
	has, _ := db.Has(key, nil)
	if has {
		ttl := strToInt64(string(args[1]))
		if ttl < 1 {
			return nil, errors.New("TTL must > 0, you set to " + string(args[1]))
		}
		bs := uint64ToBytes(uint64(time.Now().UTC().Unix() + ttl))
		if meta.Put(key, bs, nil) == nil {
			return int64(1), nil
		}
	}
	return int64(0), nil
}

// Setx will set a value by the key and expire it after timeout.
// Args: key string, value any, seconds int
func Setx(args [][]byte) (interface{}, error) {
	if len(args) < 3 {
		return nil, errNosArgs
	}
	key := encodeKvKey(args[0])

	ttl := strToInt64(string(args[2]))
	if ttl < 1 {
		return nil, errors.New("TTL must > 0, you set to " + string(args[2]))
	}
	bs := uint64ToBytes(uint64(time.Now().UTC().Unix() + ttl))
	meta.Put(key, bs, nil)

	return nil, db.Put(key, args[1], nil)
}

// TTL will return the lifetime of the key.
// Args: key string
func TTL(args [][]byte) (interface{}, error) {
	if len(args) < 1 {
		return int64(-1), errNosArgs
	}

	key := encodeKvKey(args[0])
	b, _ := meta.Get(key, nil)
	if len(b) < 1 {
		return int64(-1), nil
	}
	ttl := int64(bytesToUint64(b)) - time.Now().UTC().Unix()
	if ttl < 0 {
		ttl = -1
		meta.Delete(key, nil)
		db.Delete(key, nil)
	}
	return ttl, nil
}

func keys(args [][]byte, reverse bool) ([]string, error) {
	if len(args) < 3 {
		return []string{}, errNosArgs
	}

	ks := encodeKvKey(args[0])
	ke := encodeKvKey(args[1])
	limit, _ := strconv.Atoi(string(args[2]))

	var keys []string
	iter := db.NewIterator(&util.Range{Start: ks, Limit: ke}, nil)
	if reverse {
		iter.Seek(ke)
		for iter.Prev() {
			k := decodeKvKey(iter.Key())
			keys = append(keys, string(k))
			limit--
			if limit == 0 {
				break
			}
		}
	} else {
		for iter.Next() {
			k := decodeKvKey(iter.Key())
			keys = append(keys, string(k))
			limit--
			if limit == 0 {
				break
			}
		}
	}
	iter.Release()
	err := iter.Error()
	return keys, err
}

// Keys will list keys in the range.
// Args: start_key string, end_key string, limit_number int
func Keys(args [][]byte) ([]string, error) {
	return keys(args, false)
}

// Rkeys will reverse list keys in the range.
// Args: start_key string, end_key string, limit_number int
func Rkeys(args [][]byte) ([]string, error) {
	return keys(args, true)
}

func scan(args [][]byte, reverse bool) ([]string, error) {
	if len(args) < 3 {
		return []string{}, errNosArgs
	}

	ks := encodeKvKey(args[0])
	ke := encodeKvKey(args[1])
	limit, _ := strconv.Atoi(string(args[2]))

	var ret []string
	iter := db.NewIterator(&util.Range{Start: ks, Limit: ke}, nil)
	if reverse {
		iter.Seek(ke)
		for iter.Prev() {
			k := decodeKvKey(iter.Key())
			ret = append(ret, string(k))
			ret = append(ret, string(iter.Value()))
			limit--
			if limit == 0 {
				break
			}
		}
	} else {
		for iter.Next() {
			k := decodeKvKey(iter.Key())
			ret = append(ret, string(k))
			ret = append(ret, string(iter.Value()))
			limit--
			if limit == 0 {
				break
			}
		}
	}
	iter.Release()
	err := iter.Error()
	return ret, err
}

// Scan will list KV pair that keys in the range.
// Args: start_key string, end_key string, limit_number int
func Scan(args [][]byte) ([]string, error) {
	return scan(args, false)
}

// Rscan will reverse list KV pair that keys in the range.
// Args: start_key string, end_key string, limit_number int
func Rscan(args [][]byte) ([]string, error) {
	return scan(args, true)
}

// MultiGet wil batch read data from db.
func MultiGet(args [][]byte) (r []string, err error) {
	if len(args) < 1 {
		return []string{}, errNosArgs
	}
	for _, key := range args {
		v, _ := db.Get(encodeKvKey(key), nil)
		r = append(r, string(key))
		r = append(r, string(v))
	}
	return
}
<|endoftext|>


<commit_before>// Copyright 2014 Bret Jordan, All rights reserved.
//

package main

import (
	"code.google.com/p/getopt"
	"code.google.com/p/gopacket"
	"code.google.com/p/gopacket/pcap"
	"code.google.com/p/gopacket/pcapgo"
	"fmt"
	"log"
	"os"
	"time"
)

var sPcapSrcFilename = getopt.StringLong("file", 'f', "", "Filename of the source PCAP file", "string")
var sPcapNewFilename = getopt.StringLong("newfile", 'n', "", "Filename for the new PCAP file", "string")

var iNewYear = getopt.IntLong("year", 'y', 0, "Rebase to Year (yyyy)", "int")
var iNewMonth = getopt.IntLong("month", 'm', 0, "Rebase to Month (mm)", "int")
var iNewDay = getopt.IntLong("day", 'd', 0, "Rebase to Day (dd)", "int")

var bOptHelp = getopt.BoolLong("help", 0, "Help")
var bOptVer = getopt.BoolLong("version", 0, "Version")

var iCounter = 0
var iDebug = 0
var sVersion = "1.00"

func main() {
	getopt.Parse()

	if *bOptVer {
		fmt.Println("Version:", sVersion)
		os.Exit(0)
	}

	getopt.HelpColumn = 25
	if *bOptHelp || (*sPcapSrcFilename == "" || *sPcapNewFilename == "") {
		getopt.Usage()
		os.Exit(0)
	}

	// Figure out if there is a change needed for the date of each packet.  We will
	// compute the difference between what is in the first packet and what was passed
	// in via the command line arguments.
	iDiffYear := 0
	iDiffMonth := 0
	iDiffDay := 0

	pcapStartTimestamp := getFirstPacketTimestamp(*sPcapSrcFilename)

	if *iNewYear != 0 {
		iDiffYear = *iNewYear - pcapStartTimestamp.Year()
	}
	if *iNewMonth != 0 {
		iDiffMonth = *iNewMonth - int(pcapStartTimestamp.Month())
	}
	if *iNewDay != 0 {
		iDiffDay = *iNewDay - pcapStartTimestamp.Day()
	}

	if iDebug == 1 {
		fmt.Println("DEBUG: Y/M/D deltas", iDiffYear, iDiffMonth, iDiffDay)
	}
	// End compute date change

	// Get a handle to the PCAP source file so we can loop through each packet and make
	// changes as needed.
	handle, err1 := pcap.OpenOffline(*sPcapSrcFilename)
	if err1 != nil {
		log.Fatal(err1)
	}
	packetSource := gopacket.NewPacketSource(handle, handle.LinkType())

	// Create file handle to write to
	fileHandle, err2 := os.Create(*sPcapNewFilename)
	if err2 != nil {
		log.Fatal(err2)
	}
	writer := pcapgo.NewWriter(fileHandle)
	writer.WriteFileHeader(65535, handle.LinkType())

	fmt.Println("Each '.' represents 1000 packets converted.")

	// Loop through every packet and update them as needed writing the changes out to a new file
	for packet := range packetSource.Packets() {
		if iDebug == 1 {
			fmt.Println("DEBUG: ", "----------------------------------------")
		}

		// Make changes to the time stamp of this packet if a change is needed / requested
		if iDiffYear != 0 || iDiffMonth != 0 || iDiffDay != 0 {
			ts := packet.Metadata().CaptureInfo.Timestamp
			if iDebug == 1 {
				fmt.Println("DEBUG: Current timestamp", ts)
			}
			tsNew := ts.AddDate(iDiffYear, iDiffMonth, iDiffDay)
			if iDebug == 1 {
				fmt.Println("DEBUG: Updated timestamp", tsNew)
			}
			packet.Metadata().CaptureInfo.Timestamp = tsNew
		}

		// Write the packet out to the new file
		writer.WritePacket(packet.Metadata().CaptureInfo, packet.Data())

		// Write some output to the screen so users know we are doing something
		iCounter++
		if iCounter%1000 == 0 {
			fmt.Print(".")
			if iCounter%80000 == 0 {
				fmt.Print("\n")
			}
		}
	}
	fileHandle.Close()
	fmt.Println("\nNumber of packets processed:", iCounter)

} // main()

// We need to open the pcap file and read the timestamp from the first packet so that we can figure
// out an offset for all future packets.  This will address the problem of the pcap spanning multiple
// days, months, years  as we will always add the same amount of offset to each packet.
func getFirstPacketTimestamp(sFilename string) time.Time {
	handle, err := pcap.OpenOffline(sFilename)
	if err != nil {
		log.Fatal(err)
	}
	_, packetHeaderInfo, _ := handle.ReadPacketData()
	ts := packetHeaderInfo.Timestamp
	if iDebug == 1 {
		fmt.Println("DEBUG: Timestamp of first packet", ts)
	}
	return ts
}
<commit_msg>Added support for layer 2 changes<commit_after>// Copyright 2014 Bret Jordan, All rights reserved.
//

package main

import (
	"code.google.com/p/getopt"
	"code.google.com/p/gopacket"
	"code.google.com/p/gopacket/pcap"
	"code.google.com/p/gopacket/pcapgo"
	"encoding/hex"
	"fmt"
	"log"
	"net"
	"os"
	"strings"
	"time"
)

var sOptPcapSrcFilename = getopt.StringLong("file", 'f', "", "Filename of the source PCAP file", "string")
var sOptPcapNewFilename = getopt.StringLong("newfile", 'n', "", "Filename for the new PCAP file", "string")
var sOptMacAddress = getopt.StringLong("mac", 0, "", "The MAC Address to change in AA:BB:CC:DD:EE:FF format", "string")
var sOptNewMacAddress = getopt.StringLong("newmac", 0, "", "The replacement MAC Address, required if mac is used", "string")

var iOptNewYear = getopt.IntLong("year", 'y', 0, "Rebase to Year (yyyy)", "int")
var iOptNewMonth = getopt.IntLong("month", 'm', 0, "Rebase to Month (mm)", "int")
var iOptNewDay = getopt.IntLong("day", 'd', 0, "Rebase to Day (dd)", "int")

var bOptHelp = getopt.BoolLong("help", 0, "Help")
var bOptVer = getopt.BoolLong("version", 0, "Version")

var iCounter = 0
var iDebug = 1
var sVersion = "1.01"

//
//
//
// --------------------------------------------------------------------------------
// Function Main
// --------------------------------------------------------------------------------
func main() {
	getopt.HelpColumn = 25
	getopt.SetParameters("")
	getopt.Parse()

	if *bOptVer {
		fmt.Println("Version:", sVersion)
		os.Exit(0)
	}

	if *bOptHelp || (*sOptPcapSrcFilename == "" || *sOptPcapNewFilename == "") {
		getopt.Usage()
		os.Exit(0)
	}

	// Make sure if the user supplies one Layer2 option, that they also supply the other
	if (*sOptMacAddress != "" && *sOptNewMacAddress == "") || (*sOptNewMacAddress != "" && *sOptMacAddress == "") {
		getopt.Usage()
		os.Exit(0)
	}

	//
	//
	//
	// Figure out if there is a change needed for the date of each packet.  We will
	// compute the difference between what is in the first packet and what was passed
	// in via the command line arguments.
	iDiffYear := 0
	iDiffMonth := 0
	iDiffDay := 0

	pcapStartTimestamp := getFirstPacketTimestamp(*sOptPcapSrcFilename)

	if *iOptNewYear != 0 {
		iDiffYear = *iOptNewYear - pcapStartTimestamp.Year()
	}
	if *iOptNewMonth != 0 {
		iDiffMonth = *iOptNewMonth - int(pcapStartTimestamp.Month())
	}
	if *iOptNewDay != 0 {
		iDiffDay = *iOptNewDay - pcapStartTimestamp.Day()
	}

	if iDebug == 1 {
		fmt.Println("DEBUG: Y/M/D deltas", iDiffYear, iDiffMonth, iDiffDay)
	}
	// End compute date change

	//
	//
	//
	// Figure out if we need to change a layer 2 mac address
	userSuppliedMacAddress := make([]byte, 6, 6)
	userSuppliedNewMacAddress := make([]byte, 6, 6)
	if *sOptMacAddress != "" {
		if iDebug == 1 {
			fmt.Println("DEBUG: Passed in MAC Address to Change", *sOptMacAddress)
		}
		var err error
		userSuppliedMacAddress, err = net.ParseMAC(*sOptMacAddress)
		if err != nil {
			log.Fatal(err)
		}
		if iDebug == 1 {
			fmt.Println("DEBUG: Parsed MAC Address to", userSuppliedMacAddress)
		}
	}
	if *sOptNewMacAddress != "" {
		if iDebug == 1 {
			fmt.Println("DEBUG: Passed in MAC Address to Change", *sOptNewMacAddress)
		}
		var err error
		userSuppliedNewMacAddress, err = net.ParseMAC(*sOptNewMacAddress)
		if err != nil {
			log.Fatal(err)
		}
		if iDebug == 1 {
			fmt.Println("DEBUG: Parsed MAC Address to", userSuppliedNewMacAddress)
		}
	}
	// End compute layer 2 change

	//
	//
	//
	// Get a handle to the PCAP source file so we can loop through each packet and make
	// changes as needed.
	handle, err1 := pcap.OpenOffline(*sOptPcapSrcFilename)
	if err1 != nil {
		log.Fatal(err1)
	}
	packetSource := gopacket.NewPacketSource(handle, handle.LinkType())

	// Create file handle to write to
	fileHandle, err2 := os.Create(*sOptPcapNewFilename)
	if err2 != nil {
		log.Fatal(err2)
	}
	writer := pcapgo.NewWriter(fileHandle)
	writer.WriteFileHeader(65535, handle.LinkType())

	fmt.Println("Each '.' represents 1000 packets converted.")

	//
	//
	//
	// Loop through every packet and update them as needed writing the changes out to a new file
	for packet := range packetSource.Packets() {
		if iDebug == 1 {
			fmt.Println("DEBUG: ", "----------------------------------------")
		}

		//
		//
		//
		// Make changes to the time stamp of this packet if a change is needed / requested
		if iDiffYear != 0 || iDiffMonth != 0 || iDiffDay != 0 {
			ts := packet.Metadata().CaptureInfo.Timestamp
			if iDebug == 1 {
				fmt.Println("DEBUG: Current timestamp", ts)
			}
			tsNew := ts.AddDate(iDiffYear, iDiffMonth, iDiffDay)
			if iDebug == 1 {
				fmt.Println("DEBUG: Updated timestamp", tsNew)
			}
			packet.Metadata().CaptureInfo.Timestamp = tsNew
		}

		//
		//
		//
		// Lets compare the mac address supplied with the one in the pcap file for both
		// the DST MAC and SRC MAC but only if a MAC address is supplied as an ARG
		if *sOptMacAddress != "" {
			dstMacAddressFromPacket := packet.LinkLayer().LayerContents()[0:6]
			bDstMacAddressMatch := areByteSlicesEqual(dstMacAddressFromPacket, userSuppliedMacAddress)
			if bDstMacAddressMatch {
				if iDebug == 1 {
					fmt.Println("There is a match on the DST MAC Address, updating", makePrettyMacAddress(userSuppliedMacAddress), "to", makePrettyMacAddress(userSuppliedNewMacAddress))
				}

				for i := 0; i < 6; i++ {
					packet.LinkLayer().LayerContents()[i] = userSuppliedNewMacAddress[i]
				}
			}

			srcMacAddressFromPacket := packet.LinkLayer().LayerContents()[6:12]
			bSrcMacAddressMatch := areByteSlicesEqual(srcMacAddressFromPacket, userSuppliedMacAddress)
			if bSrcMacAddressMatch {
				if iDebug == 1 {
					fmt.Println("There is a match on the SRC MAC Address, updating", makePrettyMacAddress(userSuppliedMacAddress), "to", makePrettyMacAddress(userSuppliedNewMacAddress))
				}

				j := 0
				for i := 6; i < 12; i++ {
					packet.LinkLayer().LayerContents()[i] = userSuppliedNewMacAddress[j]
					j++
				}
			}
		}

		makePrettyMacAddress(packet.LinkLayer().LayerContents()[0:6])
		//srcMacAddress := packet.LinkLayer().LayerContents()[6:12]

		//
		//
		// Write the packet out to the new file
		writer.WritePacket(packet.Metadata().CaptureInfo, packet.Data())

		// Write some output to the screen so users know we are doing something
		iCounter++
		if iCounter%1000 == 0 {
			fmt.Print(".")
			if iCounter%80000 == 0 {
				fmt.Print("\n")
			}
		}
	} // End loop through every packet

	fileHandle.Close()
	fmt.Println("\nNumber of packets processed:", iCounter)

} // main()

//
//
//
// --------------------------------------------------------------------------------
// getFirstPacketTimestamp
// --------------------------------------------------------------------------------
// We need to open the pcap file and read the timestamp from the first packet so
// that we can figure out an offset for all future packets.  This will address the
// problem of the pcap spanning multiple days, months, years  as we will always
// add the same amount of offset to each packet.
func getFirstPacketTimestamp(sFilename string) time.Time {
	handle, err := pcap.OpenOffline(sFilename)
	if err != nil {
		log.Fatal(err)
	}
	_, packetHeaderInfo, _ := handle.ReadPacketData()
	ts := packetHeaderInfo.Timestamp
	if iDebug == 1 {
		fmt.Println("DEBUG: Timestamp of first packet", ts)
	}
	return ts
}

//
//
//
// --------------------------------------------------------------------------------
//  makePrettyMacAddress
// --------------------------------------------------------------------------------
// This function will create a human readable MAC address in upper case using
// the : notation between octets
func makePrettyMacAddress(mac []byte) string {
	sMAC := strings.ToUpper(hex.EncodeToString(mac))
	var sNewMAC string

	// This will add a ":" after ever ODD index value but not on the last one
	for i, value := range sMAC {
		sNewMAC += string(value)
		if i%2 != 0 && i%11 != 0 {
			sNewMAC += ":"
		}
	}
	if iDebug == 2 {
		fmt.Println("DEBUG: MAC Address", sNewMAC)
	}

	return sNewMAC
}

//
//
//
// --------------------------------------------------------------------------------
//  areByteSlicesEqual
// --------------------------------------------------------------------------------
// Compare two byte slices to see if they are the same
func areByteSlicesEqual(a, b []byte) bool {
	if len(a) != len(b) {
		return false
	}

	for i := range a {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"io/ioutil"
	"os"
	"testing"

	"code.google.com/p/vitess/go/zk"
	"launchpad.net/gozk/zookeeper"
)

const (
	fakeSRV = `{
"Entries": [
  {
    "host": "test1",
    "named_port_map": {"_http":8080},
    "ipv4": "0.0.0.1"
  },
  {
    "host": "test2",
    "named_port_map": {"_http":8080},
    "ipv4": "0.0.0.2"
  }
]}`

	fakeCNAME = `{
"Entries": [
  {
    "host": "test1"
  }
]}`

	fakeA = `{
"Entries": [
  {
    "host": "test1",
    "ipv4": "0.0.0.1"
  }
]}`
)

var zconn = &TestZkConn{map[string]string{
	"/zk/test/zkns/srv":   fakeSRV,
	"/zk/test/zkns/cname": fakeCNAME,
	"/zk/test/zkns/a":     fakeA,
}}

var queries = []string{
	"Q\t_http.srv.zkns.test.zk\tIN\tANY\t-1\t1.1.1.1\t1.1.1.2",
	"Q\ta.zkns.test.zk\tIN\tANY\t-1\t1.1.1.1\t1.1.1.2",
	"Q\tcname.zkns.test.zk\tIN\tANY\t-1\t1.1.1.1\t1.1.1.2",
	"Q\tempty.zkns.test.zk\tIN\tANY\t-1\t1.1.1.1\t1.1.1.2",
	"Q\bad.domain\tIN\tANY\t-1\t1.1.1.1\t1.1.1.2",
}

var results = []string{
	"OK\tzkns2pdns\nDATA\t_http.srv.zkns.test.zk\tIN\tSRV\t1\t1\t0\t0 8080 test1\nDATA\t_http.srv.zkns.test.zk\tIN\tSRV\t1\t1\t0\t0 8080 test2\nDATA\t_http.srv.zkns.test.zk\tIN\tSOA\t1\t1\t" + fqdn() + " hostmaster@" + fqdn() + " 0 1800 600 3600 300\nEND\n",
	"OK\tzkns2pdns\nDATA\ta.zkns.test.zk\tIN\tA\t1\t1\t0.0.0.1\nDATA\ta.zkns.test.zk\tIN\tSOA\t1\t1\t" + fqdn() + " hostmaster@" + fqdn() + " 0 1800 600 3600 300\nDATA\ta.zkns.test.zk\tIN\tCNAME\t1\t1\ttest1\nEND\n",
	"OK\tzkns2pdns\nDATA\tcname.zkns.test.zk\tIN\tSOA\t1\t1\t" + fqdn() + " hostmaster@" + fqdn() + " 0 1800 600 3600 300\nDATA\tcname.zkns.test.zk\tIN\tCNAME\t1\t1\ttest1\nEND\n",
	"OK\tzkns2pdns\nDATA\tempty.zkns.test.zk\tIN\tSOA\t1\t1\t" + fqdn() + " hostmaster@" + fqdn() + " 0 1800 600 3600 300\nEND\n",
	"OK\tzkns2pdns\nFAIL\n",
}

func testQuery(t *testing.T, query, result string) {
	inpr, inpw, err := os.Pipe()
	if err != nil {
		panic(err)
	}
	defer inpr.Close()
	defer inpw.Close()
	outpr, outpw, err := os.Pipe()
	if err != nil {
		panic(err)
	}
	defer outpr.Close()
	defer outpw.Close()

	zr1 := newZknsResolver(zconn, fqdn(), ".zkns.test.zk", "/zk/test/zkns")
	pd := &pdns{zr1}
	go func() {
		pd.Serve(inpr, outpw)
		outpw.Close()
	}()

	_, err = io.WriteString(inpw, "HELO\t2\n")
	if err != nil {
		t.Fatalf("write failed: %v", err)
	}
	_, err = io.WriteString(inpw, query)
	if err != nil {
		t.Fatalf("write failed: %v", err)
	}

	inpw.Close()
	data, err := ioutil.ReadAll(outpr)
	if err != nil {
		t.Fatalf("read failed: %v", err)
	}
	qresult := string(data)
	if qresult != result {
		t.Fatalf("data mismatch: found %#v expected %#v", qresult, result)
	}
}

func TestQueries(t *testing.T) {
	for i, q := range queries {
		testQuery(t, q, results[i])
	}
}

// FIXME(msolomon) move to zk/fake package
type TestZkConn struct {
	data map[string]string
}

func (conn *TestZkConn) Get(path string) (data string, stat zk.Stat, err error) {
	data, ok := conn.data[path]
	if !ok {
		err = &zookeeper.Error{Op: "TestZkConn: node doesn't exist", Code: zookeeper.ZNONODE, Path: path}
		return
	}
	s := &zk.ZkStat{}
	return data, s, nil
}

func (conn *TestZkConn) GetW(path string) (data string, stat zk.Stat, watch <-chan zookeeper.Event, err error) {
	panic("Should not be used")
}

func (conn *TestZkConn) Children(path string) (children []string, stat zk.Stat, err error) {
	panic("Should not be used")
}

func (conn *TestZkConn) ChildrenW(path string) (children []string, stat zk.Stat, watch <-chan zookeeper.Event, err error) {
	panic("Should not be used")
}

func (conn *TestZkConn) Exists(path string) (stat zk.Stat, err error) {
	_, ok := conn.data[path]
	if ok {
		return &zk.ZkStat{}, nil
	}
	return nil, nil
}

func (conn *TestZkConn) ExistsW(path string) (stat zk.Stat, watch <-chan zookeeper.Event, err error) {
	panic("Should not be used")
}

func (conn *TestZkConn) Create(path, value string, flags int, aclv []zookeeper.ACL) (pathCreated string, err error) {
	panic("Should not be used")
}

func (conn *TestZkConn) Set(path, value string, version int) (stat zk.Stat, err error) {
	panic("Should not be used")
}

func (conn *TestZkConn) Delete(path string, version int) (err error) {
	panic("Should not be used")
}

func (conn *TestZkConn) Close() error {
	panic("Should not be used")
}

func (conn *TestZkConn) RetryChange(path string, flags int, acl []zookeeper.ACL, changeFunc zookeeper.ChangeFunc) error {
	panic("Should not be used")
}

func (conn *TestZkConn) ACL(path string) ([]zookeeper.ACL, zk.Stat, error) {
	panic("Should not be used")
}

func (conn *TestZkConn) SetACL(path string, aclv []zookeeper.ACL, version int) error {
	panic("Should not be used")
}
<commit_msg>Fixing a double file.Close() call in tests.<commit_after>package main

import (
	"io"
	"io/ioutil"
	"os"
	"testing"

	"code.google.com/p/vitess/go/zk"
	"launchpad.net/gozk/zookeeper"
)

const (
	fakeSRV = `{
"Entries": [
  {
    "host": "test1",
    "named_port_map": {"_http":8080},
    "ipv4": "0.0.0.1"
  },
  {
    "host": "test2",
    "named_port_map": {"_http":8080},
    "ipv4": "0.0.0.2"
  }
]}`

	fakeCNAME = `{
"Entries": [
  {
    "host": "test1"
  }
]}`

	fakeA = `{
"Entries": [
  {
    "host": "test1",
    "ipv4": "0.0.0.1"
  }
]}`
)

var zconn = &TestZkConn{map[string]string{
	"/zk/test/zkns/srv":   fakeSRV,
	"/zk/test/zkns/cname": fakeCNAME,
	"/zk/test/zkns/a":     fakeA,
}}

var queries = []string{
	"Q\t_http.srv.zkns.test.zk\tIN\tANY\t-1\t1.1.1.1\t1.1.1.2",
	"Q\ta.zkns.test.zk\tIN\tANY\t-1\t1.1.1.1\t1.1.1.2",
	"Q\tcname.zkns.test.zk\tIN\tANY\t-1\t1.1.1.1\t1.1.1.2",
	"Q\tempty.zkns.test.zk\tIN\tANY\t-1\t1.1.1.1\t1.1.1.2",
	"Q\bad.domain\tIN\tANY\t-1\t1.1.1.1\t1.1.1.2",
}

var results = []string{
	"OK\tzkns2pdns\nDATA\t_http.srv.zkns.test.zk\tIN\tSRV\t1\t1\t0\t0 8080 test1\nDATA\t_http.srv.zkns.test.zk\tIN\tSRV\t1\t1\t0\t0 8080 test2\nDATA\t_http.srv.zkns.test.zk\tIN\tSOA\t1\t1\t" + fqdn() + " hostmaster@" + fqdn() + " 0 1800 600 3600 300\nEND\n",
	"OK\tzkns2pdns\nDATA\ta.zkns.test.zk\tIN\tA\t1\t1\t0.0.0.1\nDATA\ta.zkns.test.zk\tIN\tSOA\t1\t1\t" + fqdn() + " hostmaster@" + fqdn() + " 0 1800 600 3600 300\nDATA\ta.zkns.test.zk\tIN\tCNAME\t1\t1\ttest1\nEND\n",
	"OK\tzkns2pdns\nDATA\tcname.zkns.test.zk\tIN\tSOA\t1\t1\t" + fqdn() + " hostmaster@" + fqdn() + " 0 1800 600 3600 300\nDATA\tcname.zkns.test.zk\tIN\tCNAME\t1\t1\ttest1\nEND\n",
	"OK\tzkns2pdns\nDATA\tempty.zkns.test.zk\tIN\tSOA\t1\t1\t" + fqdn() + " hostmaster@" + fqdn() + " 0 1800 600 3600 300\nEND\n",
	"OK\tzkns2pdns\nFAIL\n",
}

func testQuery(t *testing.T, query, result string) {
	inpr, inpw, err := os.Pipe()
	if err != nil {
		panic(err)
	}
	defer inpr.Close()
	outpr, outpw, err := os.Pipe()
	if err != nil {
		inpw.Close()
		panic(err)
	}
	defer outpr.Close()

	zr1 := newZknsResolver(zconn, fqdn(), ".zkns.test.zk", "/zk/test/zkns")
	pd := &pdns{zr1}
	go func() {
		pd.Serve(inpr, outpw)
		outpw.Close()
	}()

	_, err = io.WriteString(inpw, "HELO\t2\n")
	if err != nil {
		inpw.Close()
		t.Fatalf("write failed: %v", err)
	}
	_, err = io.WriteString(inpw, query)
	if err != nil {
		inpw.Close()
		t.Fatalf("write failed: %v", err)
	}

	inpw.Close()
	data, err := ioutil.ReadAll(outpr)
	if err != nil {
		t.Fatalf("read failed: %v", err)
	}
	qresult := string(data)
	if qresult != result {
		t.Fatalf("data mismatch: found %#v expected %#v", qresult, result)
	}
}

func TestQueries(t *testing.T) {
	for i, q := range queries {
		testQuery(t, q, results[i])
	}
}

// FIXME(msolomon) move to zk/fake package
type TestZkConn struct {
	data map[string]string
}

func (conn *TestZkConn) Get(path string) (data string, stat zk.Stat, err error) {
	data, ok := conn.data[path]
	if !ok {
		err = &zookeeper.Error{Op: "TestZkConn: node doesn't exist", Code: zookeeper.ZNONODE, Path: path}
		return
	}
	s := &zk.ZkStat{}
	return data, s, nil
}

func (conn *TestZkConn) GetW(path string) (data string, stat zk.Stat, watch <-chan zookeeper.Event, err error) {
	panic("Should not be used")
}

func (conn *TestZkConn) Children(path string) (children []string, stat zk.Stat, err error) {
	panic("Should not be used")
}

func (conn *TestZkConn) ChildrenW(path string) (children []string, stat zk.Stat, watch <-chan zookeeper.Event, err error) {
	panic("Should not be used")
}

func (conn *TestZkConn) Exists(path string) (stat zk.Stat, err error) {
	_, ok := conn.data[path]
	if ok {
		return &zk.ZkStat{}, nil
	}
	return nil, nil
}

func (conn *TestZkConn) ExistsW(path string) (stat zk.Stat, watch <-chan zookeeper.Event, err error) {
	panic("Should not be used")
}

func (conn *TestZkConn) Create(path, value string, flags int, aclv []zookeeper.ACL) (pathCreated string, err error) {
	panic("Should not be used")
}

func (conn *TestZkConn) Set(path, value string, version int) (stat zk.Stat, err error) {
	panic("Should not be used")
}

func (conn *TestZkConn) Delete(path string, version int) (err error) {
	panic("Should not be used")
}

func (conn *TestZkConn) Close() error {
	panic("Should not be used")
}

func (conn *TestZkConn) RetryChange(path string, flags int, acl []zookeeper.ACL, changeFunc zookeeper.ChangeFunc) error {
	panic("Should not be used")
}

func (conn *TestZkConn) ACL(path string) ([]zookeeper.ACL, zk.Stat, error) {
	panic("Should not be used")
}

func (conn *TestZkConn) SetACL(path string, aclv []zookeeper.ACL, version int) error {
	panic("Should not be used")
}
<|endoftext|>


<commit_before>package rest

import (
	"encoding/json"
	"fmt"
	"socialapi/models"
)

func CreatePost(channelId, accountId int64) (*models.ChannelMessage, error) {
	return CreatePostWithBody(channelId, accountId, "create a message")
}

func CreatePostWithBody(channelId, accountId int64, body string) (*models.ChannelMessage, error) {
	cm := models.NewChannelMessage()
	cm.Body = body
	cm.AccountId = accountId

	return createPostRequest(channelId, cm)
}

func GetPost(id int64, accountId int64, groupName string) (*models.ChannelMessage, error) {
	url := fmt.Sprintf("/message/%d?accountId=%d&groupName=%s", id, accountId, groupName)
	cm := models.NewChannelMessage()
	cmI, err := sendModel("GET", url, cm)
	if err != nil {
		return nil, err
	}
	return cmI.(*models.ChannelMessage), nil
}

func DeletePost(id int64, accountId int64, groupName string) error {
	url := fmt.Sprintf("/message/%d?accountId=%d&groupName=%s", id, accountId, groupName)
	_, err := sendRequest("DELETE", url, nil)
	return err
}

func UpdatePost(cm *models.ChannelMessage) (*models.ChannelMessage, error) {
	cm.Body = "after update"

	url := fmt.Sprintf("/message/%d", cm.Id)
	cmI, err := sendModel("POST", url, cm)
	if err != nil {
		return nil, err
	}

	return cmI.(*models.ChannelMessage), nil
}

type PayloadRequest struct {
	Body      string                 `json:"body"`
	AccountId int64                  `json:"accountId,string"`
	Payload   map[string]interface{} `json:"payload"`
}

func CreatePostWithPayload(channelId, accountId int64, payload map[string]interface{}) (*models.ChannelMessage, error) {
	pr := PayloadRequest{}
	pr.Body = "message with payload"
	pr.AccountId = accountId
	pr.Payload = payload

	return createPostRequest(channelId, pr)
}

func createPostRequest(channelId int64, model interface{}) (*models.ChannelMessage, error) {
	url := fmt.Sprintf("/channel/%d/message", channelId)
	res, err := marshallAndSendRequest("POST", url, model)
	if err != nil {
		return nil, err
	}

	container := models.NewChannelMessageContainer()
	err = json.Unmarshal(res, container)
	if err != nil {
		return nil, err
	}

	return container.Message, nil
}
<commit_msg>socialapi: add GetPostBySlug rest helper<commit_after>package rest

import (
	"encoding/json"
	"fmt"
	"socialapi/models"
)

func CreatePost(channelId, accountId int64) (*models.ChannelMessage, error) {
	return CreatePostWithBody(channelId, accountId, "create a message")
}

func CreatePostWithBody(channelId, accountId int64, body string) (*models.ChannelMessage, error) {
	cm := models.NewChannelMessage()
	cm.Body = body
	cm.AccountId = accountId

	return createPostRequest(channelId, cm)
}

func GetPost(id int64, accountId int64, groupName string) (*models.ChannelMessage, error) {
	url := fmt.Sprintf("/message/%d?accountId=%d&groupName=%s", id, accountId, groupName)
	cm := models.NewChannelMessage()
	cmI, err := sendModel("GET", url, cm)
	if err != nil {
		return nil, err
	}
	return cmI.(*models.ChannelMessage), nil
}

func GetPostBySlug(slug string, accountId int64) (*models.ChannelMessageContainer, error) {
	url := fmt.Sprintf("/message/slug/%s?accountId=%d", slug, accountId)
	cmc := models.NewChannelMessageContainer()
	cmI, err := sendModel("GET", url, cmc)
	if err != nil {
		return nil, err
	}
	return cmI.(*models.ChannelMessageContainer), nil
}

func DeletePost(id int64, accountId int64, groupName string) error {
	url := fmt.Sprintf("/message/%d?accountId=%d&groupName=%s", id, accountId, groupName)
	_, err := sendRequest("DELETE", url, nil)
	return err
}

func UpdatePost(cm *models.ChannelMessage) (*models.ChannelMessage, error) {
	cm.Body = "after update"

	url := fmt.Sprintf("/message/%d", cm.Id)
	cmI, err := sendModel("POST", url, cm)
	if err != nil {
		return nil, err
	}

	return cmI.(*models.ChannelMessage), nil
}

type PayloadRequest struct {
	Body      string                 `json:"body"`
	AccountId int64                  `json:"accountId,string"`
	Payload   map[string]interface{} `json:"payload"`
}

func CreatePostWithPayload(channelId, accountId int64, payload map[string]interface{}) (*models.ChannelMessage, error) {
	pr := PayloadRequest{}
	pr.Body = "message with payload"
	pr.AccountId = accountId
	pr.Payload = payload

	return createPostRequest(channelId, pr)
}

func createPostRequest(channelId int64, model interface{}) (*models.ChannelMessage, error) {
	url := fmt.Sprintf("/channel/%d/message", channelId)
	res, err := marshallAndSendRequest("POST", url, model)
	if err != nil {
		return nil, err
	}

	container := models.NewChannelMessageContainer()
	err = json.Unmarshal(res, container)
	if err != nil {
		return nil, err
	}

	return container.Message, nil
}
<|endoftext|>