summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorey Hulen <corey@hulen.com>2015-07-06 11:24:06 -0800
committerCorey Hulen <corey@hulen.com>2015-07-06 11:24:06 -0800
commit3dec509899f60ca0d2eadfcc192ccc49969852ef (patch)
treea86552979d6fab4dbe336171ade9d3e69b64fff0
parent10b625ba1740c6177cfe5c06484f4a14867523bd (diff)
parent34fb817a4a4cd2761ba35a2c94f9d0eb79d06244 (diff)
downloadchat-3dec509899f60ca0d2eadfcc192ccc49969852ef.tar.gz
chat-3dec509899f60ca0d2eadfcc192ccc49969852ef.tar.bz2
chat-3dec509899f60ca0d2eadfcc192ccc49969852ef.zip
Merge pull request #131 from mattermost/mm-1391
Fixes mm-1391 adding travis CI
-rw-r--r--.travis.yml33
-rw-r--r--Godeps/Godeps.json13
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/CHANGELOG.md47
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/CONTRIBUTING.md7
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/LICENSE19
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/README.md347
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/api.go180
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/app.go255
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/batch_result.go52
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/const.go74
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/facebook_test.go1469
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/misc.go131
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/paging_result.go146
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/params.go227
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/result.go1097
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/session.go667
-rw-r--r--Godeps/_workspace/src/github.com/huandu/facebook/type.go127
-rw-r--r--Godeps/_workspace/src/golang.org/x/image/bmp/reader.go199
-rw-r--r--Godeps/_workspace/src/golang.org/x/image/bmp/reader_test.go75
-rw-r--r--Godeps/_workspace/src/golang.org/x/image/bmp/writer.go166
-rw-r--r--Godeps/_workspace/src/golang.org/x/image/bmp/writer_test.go91
-rw-r--r--Makefile22
-rw-r--r--api/api_test.go3
-rw-r--r--api/auto_users.go5
-rw-r--r--api/channel_benchmark_test.go3
-rw-r--r--api/channel_test.go55
-rw-r--r--api/command_test.go9
-rw-r--r--api/file_test.go11
-rw-r--r--api/post_test.go31
-rw-r--r--api/team_test.go23
-rw-r--r--api/user_test.go53
-rw-r--r--api/web_socket_test.go5
-rw-r--r--config/config.json2
-rw-r--r--store/sql_audit_store_test.go15
-rw-r--r--store/sql_channel_store_test.go74
-rw-r--r--store/sql_post_store_test.go6
-rw-r--r--store/sql_session_store_test.go16
-rw-r--r--store/sql_store.go10
-rw-r--r--store/sql_team_store_test.go13
-rw-r--r--store/sql_user_store.go2
-rw-r--r--store/sql_user_store_test.go22
-rw-r--r--store/store.go9
42 files changed, 794 insertions, 5017 deletions
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 000000000..55ab2986e
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,33 @@
+language: go
+
+go:
+ - 1.4.2
+
+before_install:
+ - gem install compass
+ - "sudo apt-get update -qq"
+
+ - "sudo apt-get remove mysql-common mysql-server-5.5 mysql-server-core-5.5 mysql-client-5.5 mysql-client-core-5.5"
+ - "sudo apt-get autoremove"
+ - "sudo apt-get install libaio1"
+ - "wget -O mysql-5.6.17.deb http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.17-debian6.0-x86_64.deb"
+ - "sudo dpkg -i mysql-5.6.17.deb"
+ - "sudo cp /opt/mysql/server-5.6/support-files/mysql.server /etc/init.d/mysql.server"
+ - "sudo ln -s /opt/mysql/server-5.6/bin/* /usr/bin/"
+ # some config values were changed since 5.5
+ - "sudo sed -i'' 's/table_cache/table_open_cache/' /etc/mysql/my.cnf"
+ - "sudo sed -i'' 's/log_slow_queries/slow_query_log/' /etc/mysql/my.cnf"
+ - "sudo sed -i'' 's/basedir[^=]\\+=.*$/basedir = \\/opt\\/mysql\\/server-5.6/' /etc/mysql/my.cnf"
+ - "sudo /etc/init.d/mysql.server start"
+
+before_script:
+ - mysql -e "CREATE DATABASE IF NOT EXISTS mattermost_test ;" -uroot
+ - mysql -e "CREATE USER 'mmuser'@'%' IDENTIFIED BY 'mostest' ;" -uroot
+ - mysql -e "GRANT ALL ON mattermost_test.* TO 'mmuser'@'%' ;" -uroot
+
+services:
+ - redis-server
+
+addons:
+ hosts:
+ - 127.0.0.1 dockerhost \ No newline at end of file
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 093b2a1fc..db118f512 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -89,11 +89,6 @@
"Rev": "6fd0f867fef40c540fa05c59f86396de10a632a6"
},
{
- "ImportPath": "github.com/huandu/facebook",
- "Comment": "v1.5.2",
- "Rev": "7c46d89211b9a3f01087f47f6a399b815801ade4"
- },
- {
"ImportPath": "github.com/mssola/user_agent",
"Comment": "v0.4.1-2-g35c7f18",
"Rev": "35c7f18f5261cc18c698a461053c119aebaf8542"
@@ -123,6 +118,10 @@
"Rev": "74f810a0152f4c50a16195f6b9ff44afc35594e8"
},
{
+ "ImportPath": "golang.org/x/image/bmp",
+ "Rev": "eb11b45157c1b71f30b3cec66306f1cd779a689e"
+ },
+ {
"ImportPath": "gopkg.in/bufio.v1",
"Comment": "v1",
"Rev": "567b2bfa514e796916c4747494d6ff5132a1dfce"
@@ -136,10 +135,6 @@
"ImportPath": "gopkg.in/redis.v2",
"Comment": "v2.3.2",
"Rev": "e6179049628164864e6e84e973cfb56335748dea"
- },
- {
- "ImportPath": "golang.org/x/image/bmp",
- "Rev": "eb11b45157c1b71f30b3cec66306f1cd779a689e"
}
]
}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/CHANGELOG.md b/Godeps/_workspace/src/github.com/huandu/facebook/CHANGELOG.md
deleted file mode 100644
index d1c14a215..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/CHANGELOG.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# Change Log #
-
-## v1.5.2 ##
-
-* `[FIX]` [#32](https://github.com/huandu/facebook/pull/32) BatchApi/Batch returns facebook error when access token is not valid.
-
-## v1.5.1 ##
-
-* `[FIX]` [#31](https://github.com/huandu/facebook/pull/31) When `/oauth/access_token` returns a query string instead of json, this package can correctly handle it.
-
-## v1.5.0 ##
-
-* `[NEW]` [#28](https://github.com/huandu/facebook/pull/28) Support debug mode introduced by facebook graph API v2.3.
-* `[FIX]` Removed all test cases depending on facebook graph API v1.0.
-
-## v1.4.1 ##
-
-* `[NEW]` [#27](https://github.com/huandu/facebook/pull/27) Timestamp value in Graph API response can be decoded as a `time.Time` value now. Thanks, [@Lazyshot](https://github.com/Lazyshot).
-
-## v1.4.0 ##
-
-* `[FIX]` [#23](https://github.com/huandu/facebook/issues/24) Algorithm change: Camel case string to underscore string supports abbreviation
-
-Fix for [#23](https://github.com/huandu/facebook/issues/24) could be a breaking change. Camel case string `HTTPServer` will be converted to `http_server` instead of `h_t_t_p_server`. See issue description for detail.
-
-## v1.3.0 ##
-
-* `[NEW]` [#22](https://github.com/huandu/facebook/issues/22) Add a new helper struct `BatchResult` to hold batch request responses.
-
-## v1.2.0 ##
-
-* `[NEW]` [#20](https://github.com/huandu/facebook/issues/20) Add Decode functionality for paging results. Thanks, [@cbroglie](https://github.com/cbroglie).
-* `[FIX]` [#21](https://github.com/huandu/facebook/issues/21) `Session#Inspect` cannot return error if access token is invalid.
-
-Fix for [#21](https://github.com/huandu/facebook/issues/21) will result a possible breaking change in `Session#Inspect`. It was return whole result returned by facebook inspect api. Now it only return its "data" sub-tree. As facebook puts everything including error message in "data" sub-tree, I believe it's reasonable to make this change.
-
-## v1.1.0 ##
-
-* `[FIX]` [#19](https://github.com/huandu/facebook/issues/19) Any valid int64 number larger than 2^53 or smaller than -2^53 can be correctly decoded without precision lost.
-
-Fix for [#19](https://github.com/huandu/facebook/issues/19) will result a possible breaking change in `Result#Get` and `Result#GetField`. If a JSON field is a number, these two functions will return json.Number instead of float64.
-
-The fix also introduces a side effect in `Result#Decode` and `Result#DecodeField`. A number field (`int*` and `float*`) can be decoded to a string. It was not allowed in previous version.
-
-## v1.0.0 ##
-
-Initial tag. Library is stable enough for all features mentioned in README.md.
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/CONTRIBUTING.md b/Godeps/_workspace/src/github.com/huandu/facebook/CONTRIBUTING.md
deleted file mode 100644
index c001d2511..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/CONTRIBUTING.md
+++ /dev/null
@@ -1,7 +0,0 @@
-Thanks for contributing this project!
-
-Please don't forget to use `gofmt` to make your code look good.
-
-Here is the command I use. Please always use the same parameters.
-
- go fmt
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/LICENSE b/Godeps/_workspace/src/github.com/huandu/facebook/LICENSE
deleted file mode 100644
index 9569215e9..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2012 - 2015 Huan Du
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/README.md b/Godeps/_workspace/src/github.com/huandu/facebook/README.md
deleted file mode 100644
index a21de8d7c..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/README.md
+++ /dev/null
@@ -1,347 +0,0 @@
-# A Facebook Graph API SDK In Golang #
-
-[![Build Status](https://travis-ci.org/huandu/facebook.png?branch=master)](https://travis-ci.org/huandu/facebook)
-
-This is a Go package fully supports Facebook Graph API with file upload, batch request, FQL and multi-FQL. It can be used in Google App Engine.
-
-API documents can be found on [godoc](http://godoc.org/github.com/huandu/facebook).
-
-Feel free to create an issue or send me a pull request if you have any "how-to" question or bug or suggestion when using this package. I'll try my best to reply it.
-
-## Get It ##
-
-Use `go get -u github.com/huandu/facebook` to get or update it.
-
-## Usage ##
-
-### Quick start ###
-
-Here is a sample to read my Facebook username by uid.
-
-```go
-package main
-
-import (
- "fmt"
- fb "github.com/huandu/facebook"
-)
-
-func main() {
- res, _ := fb.Get("/538744468", fb.Params{
- "fields": "username",
- "access_token": "a-valid-access-token",
- })
- fmt.Println("here is my facebook username:", res["username"])
-}
-```
-
-Type of `res` is `fb.Result` (a.k.a. `map[string]interface{}`).
-This type has several useful methods to decode `res` to any Go type safely.
-
-```go
-// Decode "username" to a Go string.
-var username string
-res.DecodeField("username", &username)
-fmt.Println("alternative way to get username:", username)
-
-// It's also possible to decode the whole result into a predefined struct.
-type User struct {
- Username string
-}
-
-var user User
-res.Decode(&user)
-fmt.Println("print username in struct:", user.Username)
-```
-
-### Read a graph `user` object with a valid access token ###
-
-```go
-res, err := fb.Get("/me/feed", fb.Params{
- "access_token": "a-valid-access-token",
-})
-
-if err != nil {
- // err can be an facebook API error.
- // if so, the Error struct contains error details.
- if e, ok := err.(*Error); ok {
- fmt.Logf("facebook error. [message:%v] [type:%v] [code:%v] [subcode:%v]",
- e.Message, e.Type, e.Code, e.ErrorSubcode)
- return
- }
-
- return
-}
-
-// read my last feed.
-fmt.Println("my latest feed story is:", res.Get("data.0.story"))
-```
-
-### Read a graph `search` for page and decode slice of maps
-
-```go
-res, _ := fb.Get("/search", fb.Params{
- "access_token": "a-valid-access-token",
- "type": "page",
- "q": "nightlife,singapore",
- })
-
-var items []fb.Result
-
-err := res.DecodeField("data", &items)
-
-if err != nil {
- fmt.Logf("An error has happened %v", err)
- return
-}
-
-for _, item := range items {
- fmt.Println(item["id"])
-}
-```
-
-### Use `App` and `Session` ###
-
-It's recommended to use `App` and `Session` in a production app. They provide more controls over all API calls. They can also make code clear and concise.
-
-```go
-// create a global App var to hold app id and secret.
-var globalApp = fb.New("your-app-id", "your-app-secret")
-
-// facebook asks for a valid redirect uri when parsing signed request.
-// it's a new enforced policy starting in late 2013.
-globalApp.RedirectUri = "http://your.site/canvas/url/"
-
-// here comes a client with a facebook signed request string in query string.
-// creates a new session with signed request.
-session, _ := globalApp.SessionFromSignedRequest(signedRequest)
-
-// if there is another way to get decoded access token,
-// creates a session directly with the token.
-session := globalApp.Session(token)
-
-// validate access token. err is nil if token is valid.
-err := session.Validate()
-
-// use session to send api request with access token.
-res, _ := session.Get("/me/feed", nil)
-```
-
-### Use `paging` field in response. ###
-
-Some Graph API responses use a special JSON structure to provide paging information. Use `Result.Paging()` to walk through all data in such results.
-
-```go
-res, _ := session.Get("/me/home", nil)
-
-// create a paging structure.
-paging, _ := res.Paging(session)
-
-// get current results.
-results := paging.Data()
-
-// get next page.
-noMore, err := paging.Next()
-results = paging.Data()
-```
-
-### Read graph api response and decode result into a struct ###
-
-As facebook Graph API always uses lower case words as keys in API response.
-This package can convert go's camel-case-style struct field name to facebook's underscore-style API key name.
-
-For instance, to decode following JSON response...
-
-```json
-{
- "foo_bar": "player"
-}
-```
-
-One can use following struct.
-
-```go
-type Data struct {
- FooBar string // "FooBar" maps to "foo_bar" in JSON automatically in this case.
-}
-```
-
-Decoding behavior can be changed per field through field tag -- just like what `encoding/json` does.
-
-Following is a sample shows all possible field tags.
-
-```go
-// define a facebook feed object.
-type FacebookFeed struct {
- Id string `facebook:",required"` // this field must exist in response.
- // mind the "," before "required".
- Story string
- FeedFrom *FacebookFeedFrom `facebook:"from"` // use customized field name "from"
- CreatedTime string `facebook:"created_time,required"` // both customized field name and "required" flag.
-}
-
-type FacebookFeedFrom struct {
- Name, Id string
-}
-
-// create a feed object direct from graph api result.
-var feed FacebookFeed
-res, _ := session.Get("/me/feed", nil)
-res.DecodeField("data.0", &feed) // read latest feed
-```
-
-### Send a batch request ###
-
-```go
-params1 := Params{
- "method": fb.GET,
- "relative_url": "me",
-}
-params2 := Params{
- "method": fb.GET,
- "relative_url": uint64(100002828925788),
-}
-results, err := fb.BatchApi(your_access_token, params1, params2)
-
-if err != nil {
- // check error...
- return
-}
-
-// batchResult1 and batchResult2 are response for params1 and params2.
-batchResult1, _ := results[0].Batch()
-batchResult2, _ := results[1].Batch()
-
-// Use parsed result.
-var id string
-res := batchResult1.Result
-res.DecodeField("id", &id)
-
-// Use response header.
-contentType := batchResult1.Header.Get("Content-Type")
-```
-
-### Send FQL query ###
-
-```go
-results, _ := fb.FQL("SELECT username FROM page WHERE page_id = 20531316728")
-fmt.Println(results[0]["username"]) // print "facebook"
-
-// most FQL query requires access token. create session to hold access token.
-session := &fb.Session{}
-session.SetAccessToken("A-VALID-ACCESS-TOKEN")
-results, _ := session.FQL("SELECT username FROM page WHERE page_id = 20531316728")
-fmt.Println(results[0]["username"]) // print "facebook"
-```
-
-### Make multi-FQL ###
-
-```go
-res, _ := fb.MultiFQL(Params{
- "query1": "SELECT username FROM page WHERE page_id = 20531316728",
- "query2": "SELECT uid FROM user WHERE uid = 538744468",
-})
-var query1, query2 []Result
-
-// get response for query1 and query2.
-res.DecodeField("query1", &query1)
-res.DecodeField("query2", &query2)
-
-// most FQL query requires access token. create session to hold access token.
-session := &fb.Session{}
-session.SetAccessToken("A-VALID-ACCESS-TOKEN")
-res, _ := session.MultiFQL(Params{
- "query1": "...",
- "query2": "...",
-})
-
-// same as the sample without access token...
-```
-
-### Use it in Google App Engine ###
-
-Google App Engine provide `appengine/urlfetch` package as standard http client package. Default client in `net/http` doesn't work. One must explicitly set http client in `Session` to make it work.
-
-```go
-import (
- "appengine"
- "appengine/urlfetch"
-)
-
-// suppose it's the appengine context initialized somewhere.
-var context appengine.Context
-
-// default Session object uses http.DefaultClient which is not allowed to use
-// in appengine. one has to create a Session and assign it a special client.
-seesion := globalApp.Session("a-access-token")
-session.HttpClient = urlfetch.Client(context)
-
-// now, session uses appengine http client now.
-res, err := session.Get("/me", nil)
-```
-
-### Select Graph API version ###
-
-See [Platform Versioning](https://developers.facebook.com/docs/apps/versions) to understand facebook versioning strategy.
-
-```go
-// this package uses default version which is controlled by facebook app setting.
-// change following global variable to specific a global default version.
-fb.Version = "v2.0"
-
-// starting with graph api v2.0, it's not allowed to get user information without access token.
-fb.Api("huan.du", GET, nil)
-
-// it's possible to specify version per session.
-session := &fb.Session{}
-session.Version = "v2.0" // overwrite global default.
-```
-
-### Enable `appsecret_proof` ###
-
-Facebook can verify Graph API Calls with `appsecret_proof`. It's a feature to make Graph API call more secure. See [Securing Graph API Requests](https://developers.facebook.com/docs/graph-api/securing-requests) to know more about it.
-
-```go
-globalApp := fb.New("your-app-id", "your-app-secret")
-
-// enable "appsecret_proof" for all sessions created by this app.
-globalApp.EnableAppsecretProof = true
-
-// all calls in this session are secured.
-session := globalApp.Session("a-valid-access-token")
-session.Get("/me", nil)
-
-// it's also possible to enable/disable this feature per session.
-session.EnableAppsecretProof(false)
-```
-
-### Debugging API Requests ###
-
-Facebook introduces a way to debug graph API calls. See [Debugging API Requests](https://developers.facebook.com/docs/graph-api/using-graph-api/v2.3#debugging) for details.
-
-This package provides both package level and per session debug flag. Set `Debug` to a `DEBUG_*` constant to change debug mode globally; or use `Session#SetDebug` to change debug mode for one session.
-
-When debug mode is turned on, use `Result#DebugInfo` to get `DebugInfo` struct from result.
-
-```go
-fb.Debug = fb.DEBUG_ALL
-
-res, _ := fb.Get("/me", fb.Params{"access_token": "xxx"})
-debugInfo := res.DebugInfo()
-
-fmt.Println("http headers:", debugInfo.Header)
-fmt.Println("facebook api version:", debugInfo.FacebookApiVersion)
-```
-
-## Change Log ##
-
-See [CHANGELOG.md](CHANGELOG.md).
-
-## Out of Scope ##
-
-1. No OAuth integration. This package only provides APIs to parse/verify access token and code generated in OAuth 2.0 authentication process.
-2. No old RESTful API support. Such APIs are deprecated for years. Forget about them.
-
-## License ##
-
-This package is licensed under MIT license. See LICENSE for details.
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/api.go b/Godeps/_workspace/src/github.com/huandu/facebook/api.go
deleted file mode 100644
index 57945d26e..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/api.go
+++ /dev/null
@@ -1,180 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-// This is a Go library fully supports Facebook Graph API (both 1.0 and 2.x) with
-// file upload, batch request, FQL and multi-FQL. It can be used in Google App Engine.
-//
-// Library design is highly influenced by facebook official PHP/JS SDK.
-// If you have experience with PHP/JS SDK, you may feel quite familiar with it.
-//
-// Go to project home page to see samples. Link: https://github.com/huandu/facebook
-//
-// This library doesn't implement any deprecated old RESTful API. And it won't.
-package facebook
-
-import (
- "net/http"
-)
-
-var (
- // Default facebook api version.
- // It can be any valid version string (e.g. "v2.3") or empty.
- //
- // See https://developers.facebook.com/docs/apps/versions for details.
- Version string
-
- // Set app level debug mode.
- // After setting DebugMode, all newly created session will use the mode
- // to communicate with graph API.
- //
- // See https://developers.facebook.com/docs/graph-api/using-graph-api/v2.3#debugging
- Debug DebugMode
-)
-
-// Makes a facebook graph api call with default session.
-//
-// Method can be GET, POST, DELETE or PUT.
-//
-// Params represents query strings in this call.
-// Keys and values in params will be encoded for URL automatically. So there is
-// no need to encode keys or values in params manually. Params can be nil.
-//
-// If you want to get
-// https://graph.facebook.com/huandu?fields=name,username
-// Api should be called as following
-// Api("/huandu", GET, Params{"fields": "name,username"})
-// or in a simplified way
-// Get("/huandu", Params{"fields": "name,username"})
-//
-// Api is a wrapper of Session.Api(). It's designed for graph api that doesn't require
-// app id, app secret and access token. It can be called in multiple goroutines.
-//
-// If app id, app secret or access token is required in graph api, caller should
-// create a new facebook session through App instance instead.
-func Api(path string, method Method, params Params) (Result, error) {
- return defaultSession.Api(path, method, params)
-}
-
-// Get is a short hand of Api(path, GET, params).
-func Get(path string, params Params) (Result, error) {
- return Api(path, GET, params)
-}
-
-// Post is a short hand of Api(path, POST, params).
-func Post(path string, params Params) (Result, error) {
- return Api(path, POST, params)
-}
-
-// Delete is a short hand of Api(path, DELETE, params).
-func Delete(path string, params Params) (Result, error) {
- return Api(path, DELETE, params)
-}
-
-// Put is a short hand of Api(path, PUT, params).
-func Put(path string, params Params) (Result, error) {
- return Api(path, PUT, params)
-}
-
-// Makes a batch facebook graph api call with default session.
-//
-// BatchApi supports most kinds of batch calls defines in facebook batch api document,
-// except uploading binary data. Use Batch to do so.
-//
-// Note: API response is stored in "body" field of a Result.
-// results, _ := BatchApi(accessToken, Params{...}, Params{...})
-//
-// // Use first batch api response.
-// var res1 *BatchResult
-// var err error
-// res1, err = results[0].Batch()
-//
-// if err != nil {
-// // this is not a valid batch api response.
-// }
-//
-// // Use BatchResult#Result to get response body content as Result.
-// res := res1.Result
-//
-// Facebook document: https://developers.facebook.com/docs/graph-api/making-multiple-requests
-func BatchApi(accessToken string, params ...Params) ([]Result, error) {
- return Batch(Params{"access_token": accessToken}, params...)
-}
-
-// Makes a batch facebook graph api call with default session.
-// Batch is designed for more advanced usage including uploading binary files.
-//
-// An uploading files sample
-// // equivalent to following curl command (borrowed from facebook docs)
-// // curl \
-// // -F 'access_token=…' \
-// // -F 'batch=[{"method":"POST","relative_url":"me/photos","body":"message=My cat photo","attached_files":"file1"},{"method":"POST","relative_url":"me/photos","body":"message=My dog photo","attached_files":"file2"},]' \
-// // -F 'file1=@cat.gif' \
-// // -F 'file2=@dog.jpg' \
-// // https://graph.facebook.com
-// Batch(Params{
-// "access_token": "the-access-token",
-// "file1": File("cat.gif"),
-// "file2": File("dog.jpg"),
-// }, Params{
-// "method": "POST",
-// "relative_url": "me/photos",
-// "body": "message=My cat photo",
-// "attached_files": "file1",
-// }, Params{
-// "method": "POST",
-// "relative_url": "me/photos",
-// "body": "message=My dog photo",
-// "attached_files": "file2",
-// })
-//
-// Facebook document: https://developers.facebook.com/docs/graph-api/making-multiple-requests
-func Batch(batchParams Params, params ...Params) ([]Result, error) {
- return defaultSession.Batch(batchParams, params...)
-}
-
-// Makes a FQL query with default session.
-// Returns a slice of Result. If there is no query result, the result is nil.
-//
-// FQL can only make query without "access_token". For query requiring "access_token", create
-// Session and call its FQL method.
-//
-// Facebook document: https://developers.facebook.com/docs/technical-guides/fql#query
-func FQL(query string) ([]Result, error) {
- return defaultSession.FQL(query)
-}
-
-// Makes a multi FQL query with default session.
-// Returns a parsed Result. The key is the multi query key, and the value is the query result.
-//
-// MultiFQL can only make query without "access_token". For query requiring "access_token", create
-// Session and call its MultiFQL method.
-//
-// See Session.MultiFQL document for samples.
-//
-// Facebook document: https://developers.facebook.com/docs/technical-guides/fql#multi
-func MultiFQL(queries Params) (Result, error) {
- return defaultSession.MultiFQL(queries)
-}
-
-// Makes an arbitrary HTTP request with default session.
-// It expects server responses a facebook Graph API response.
-// request, _ := http.NewRequest("https://graph.facebook.com/538744468", "GET", nil)
-// res, err := Request(request)
-// fmt.Println(res["gender"]) // get "male"
-func Request(request *http.Request) (Result, error) {
- return defaultSession.Request(request)
-}
-
-// DefaultHttpClient returns the http client for default session.
-func DefaultHttpClient() HttpClient {
- return defaultSession.HttpClient
-}
-
-// SetHttpClient updates the http client of default session.
-func SetHttpClient(client HttpClient) {
- defaultSession.HttpClient = client
-}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/app.go b/Godeps/_workspace/src/github.com/huandu/facebook/app.go
deleted file mode 100644
index d8787aa87..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/app.go
+++ /dev/null
@@ -1,255 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "bytes"
- "crypto/hmac"
- "crypto/sha256"
- "encoding/json"
- "fmt"
- "strings"
-)
-
-// Creates a new App and sets app id and secret.
-func New(appId, appSecret string) *App {
- return &App{
- AppId: appId,
- AppSecret: appSecret,
- }
-}
-
-// Gets application access token, useful for gathering public information about users and applications.
-func (app *App) AppAccessToken() string {
- return app.AppId + "|" + app.AppSecret
-}
-
-// Parses signed request.
-func (app *App) ParseSignedRequest(signedRequest string) (res Result, err error) {
- strs := strings.SplitN(signedRequest, ".", 2)
-
- if len(strs) != 2 {
- err = fmt.Errorf("invalid signed request format.")
- return
- }
-
- sig, e1 := decodeBase64URLEncodingString(strs[0])
-
- if e1 != nil {
- err = fmt.Errorf("cannot decode signed request sig. error is %v.", e1)
- return
- }
-
- payload, e2 := decodeBase64URLEncodingString(strs[1])
-
- if e2 != nil {
- err = fmt.Errorf("cannot decode signed request payload. error is %v.", e2)
- return
- }
-
- err = json.Unmarshal(payload, &res)
-
- if err != nil {
- err = fmt.Errorf("signed request payload is not a valid json string. error is %v.", err)
- return
- }
-
- var hashMethod string
- err = res.DecodeField("algorithm", &hashMethod)
-
- if err != nil {
- err = fmt.Errorf("signed request payload doesn't contains a valid 'algorithm' field.")
- return
- }
-
- hashMethod = strings.ToUpper(hashMethod)
-
- if hashMethod != "HMAC-SHA256" {
- err = fmt.Errorf("signed request payload uses an unknown HMAC method. expect 'HMAC-SHA256'. actual '%v'.", hashMethod)
- return
- }
-
- hash := hmac.New(sha256.New, []byte(app.AppSecret))
- hash.Write([]byte(strs[1])) // note: here uses the payload base64 string, not decoded bytes
- expectedSig := hash.Sum(nil)
-
- if bytes.Compare(sig, expectedSig) != 0 {
- err = fmt.Errorf("bad signed request signiture.")
- return
- }
-
- return
-}
-
-// ParseCode redeems code for a valid access token.
-// It's a shorthand call to ParseCodeInfo(code, "").
-//
-// In facebook PHP SDK, there is a CSRF state to avoid attack.
-// That state is not checked in this library.
-// Caller is responsible to store and check state if possible.
-func (app *App) ParseCode(code string) (token string, err error) {
- token, _, _, err = app.ParseCodeInfo(code, "")
- return
-}
-
-// ParseCodeInfo redeems code for access token and returns extra information.
-// The machineId is optional.
-//
-// See https://developers.facebook.com/docs/facebook-login/access-tokens#extending
-func (app *App) ParseCodeInfo(code, machineId string) (token string, expires int, newMachineId string, err error) {
- if code == "" {
- err = fmt.Errorf("code is empty")
- return
- }
-
- var res Result
- res, err = defaultSession.sendOauthRequest("/oauth/access_token", Params{
- "client_id": app.AppId,
- "redirect_uri": app.RedirectUri,
- "code": code,
- })
-
- if err != nil {
- err = fmt.Errorf("cannot parse facebook response. error is %v.", err)
- return
- }
-
- err = res.DecodeField("access_token", &token)
-
- if err != nil {
- return
- }
-
- err = res.DecodeField("expires_in", &expires)
-
- if err != nil {
- return
- }
-
- if _, ok := res["machine_id"]; ok {
- err = res.DecodeField("machine_id", &newMachineId)
- }
-
- return
-}
-
-// Exchange a short lived access token to a long lived access token.
-// Return new access token and its expires time.
-func (app *App) ExchangeToken(accessToken string) (token string, expires int, err error) {
- if accessToken == "" {
- err = fmt.Errorf("short lived accessToken is empty")
- return
- }
-
- var res Result
- res, err = defaultSession.sendOauthRequest("/oauth/access_token", Params{
- "grant_type": "fb_exchange_token",
- "client_id": app.AppId,
- "client_secret": app.AppSecret,
- "fb_exchange_token": accessToken,
- })
-
- if err != nil {
- err = fmt.Errorf("cannot parse facebook response. error is %v.", err)
- return
- }
-
- err = res.DecodeField("access_token", &token)
-
- if err != nil {
- return
- }
-
- err = res.DecodeField("expires_in", &expires)
- return
-}
-
-// Get code from a long lived access token.
-// Return the code retrieved from facebook.
-func (app *App) GetCode(accessToken string) (code string, err error) {
- if accessToken == "" {
- err = fmt.Errorf("long lived accessToken is empty")
- return
- }
-
- var res Result
- res, err = defaultSession.sendOauthRequest("/oauth/client_code", Params{
- "client_id": app.AppId,
- "client_secret": app.AppSecret,
- "redirect_uri": app.RedirectUri,
- "access_token": accessToken,
- })
-
- if err != nil {
- err = fmt.Errorf("cannot get code from facebook. error is %v.", err)
- return
- }
-
- err = res.DecodeField("code", &code)
- return
-}
-
-// Creates a session based on current App setting.
-func (app *App) Session(accessToken string) *Session {
- return &Session{
- accessToken: accessToken,
- app: app,
- enableAppsecretProof: app.EnableAppsecretProof,
- }
-}
-
-// Creates a session from a signed request.
-// If signed request contains a code, it will automatically use this code
-// to exchange a valid access token.
-func (app *App) SessionFromSignedRequest(signedRequest string) (session *Session, err error) {
- var res Result
-
- res, err = app.ParseSignedRequest(signedRequest)
-
- if err != nil {
- return
- }
-
- var id, token string
-
- res.DecodeField("user_id", &id) // it's ok without user id.
- err = res.DecodeField("oauth_token", &token)
-
- if err == nil {
- session = &Session{
- accessToken: token,
- app: app,
- id: id,
- enableAppsecretProof: app.EnableAppsecretProof,
- }
- return
- }
-
- // cannot get "oauth_token"? try to get "code".
- err = res.DecodeField("code", &token)
-
- if err != nil {
- // no code? no way to continue.
- err = fmt.Errorf("cannot find 'oauth_token' and 'code'. no way to continue.")
- return
- }
-
- token, err = app.ParseCode(token)
-
- if err != nil {
- return
- }
-
- session = &Session{
- accessToken: token,
- app: app,
- id: id,
- enableAppsecretProof: app.EnableAppsecretProof,
- }
- return
-}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/batch_result.go b/Godeps/_workspace/src/github.com/huandu/facebook/batch_result.go
deleted file mode 100644
index 43a38358e..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/batch_result.go
+++ /dev/null
@@ -1,52 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "encoding/json"
- "net/http"
-)
-
-type batchResultHeader struct {
- Name string `facebook=",required"`
- Value string `facebook=",required"`
-}
-
-type batchResultData struct {
- Code int `facebook=",required"`
- Headers []batchResultHeader `facebook=",required"`
- Body string `facebook=",required"`
-}
-
-func newBatchResult(res Result) (*BatchResult, error) {
- var data batchResultData
- err := res.Decode(&data)
-
- if err != nil {
- return nil, err
- }
-
- result := &BatchResult{
- StatusCode: data.Code,
- Header: http.Header{},
- Body: data.Body,
- }
-
- err = json.Unmarshal([]byte(result.Body), &result.Result)
-
- if err != nil {
- return nil, err
- }
-
- // add headers to result.
- for _, header := range data.Headers {
- result.Header.Add(header.Name, header.Value)
- }
-
- return result, nil
-}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/const.go b/Godeps/_workspace/src/github.com/huandu/facebook/const.go
deleted file mode 100644
index aa8be0de2..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/const.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "encoding/json"
- "reflect"
- "regexp"
- "time"
-)
-
-// Facebook graph api methods.
-const (
- GET Method = "GET"
- POST Method = "POST"
- DELETE Method = "DELETE"
- PUT Method = "PUT"
-)
-
-const (
- ERROR_CODE_UNKNOWN = -1 // unknown facebook graph api error code.
-
- _MIME_FORM_URLENCODED = "application/x-www-form-urlencoded"
-)
-
-// Graph API debug mode values.
-const (
- DEBUG_OFF DebugMode = "" // turn off debug.
-
- DEBUG_ALL DebugMode = "all"
- DEBUG_INFO DebugMode = "info"
- DEBUG_WARNING DebugMode = "warning"
-)
-
-const (
- debugInfoKey = "__debug__"
- debugProtoKey = "__proto__"
- debugHeaderKey = "__header__"
-
- facebookApiVersionHeader = "facebook-api-version"
- facebookDebugHeader = "x-fb-debug"
- facebookRevHeader = "x-fb-rev"
-)
-
-var (
- // Maps aliases to Facebook domains.
- // Copied from Facebook PHP SDK.
- domainMap = map[string]string{
- "api": "https://api.facebook.com/",
- "api_video": "https://api-video.facebook.com/",
- "api_read": "https://api-read.facebook.com/",
- "graph": "https://graph.facebook.com/",
- "graph_video": "https://graph-video.facebook.com/",
- "www": "https://www.facebook.com/",
- }
-
- // checks whether it's a video post.
- regexpIsVideoPost = regexp.MustCompile(`/^(\/)(.+)(\/)(videos)$/`)
-
- // default facebook session.
- defaultSession = &Session{}
-
- typeOfPointerToBinaryData = reflect.TypeOf(&binaryData{})
- typeOfPointerToBinaryFile = reflect.TypeOf(&binaryFile{})
- typeOfJSONNumber = reflect.TypeOf(json.Number(""))
- typeOfTime = reflect.TypeOf(time.Time{})
-
- facebookSuccessJsonBytes = []byte("true")
-)
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/facebook_test.go b/Godeps/_workspace/src/github.com/huandu/facebook/facebook_test.go
deleted file mode 100644
index 154881f38..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/facebook_test.go
+++ /dev/null
@@ -1,1469 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "bytes"
- "encoding/base64"
- "encoding/json"
- "fmt"
- "testing"
- "time"
-)
-
-const (
- FB_TEST_APP_ID = "169186383097898"
- FB_TEST_APP_SECRET = "b2e4262c306caa3c7f5215d2d099b319"
-
- // remeber to change it to a valid token to run test
- //FB_TEST_VALID_ACCESS_TOKEN = "CAACZA38ZAD8CoBAFCaVgLBNdz0RrH45yUBUA95exI1FY5i4mZBY5iULfM3YEpS53nP6eSF4cf3nmoiePHvMkdSZApkxu1heAupW7OE8tmiySRZAYkZBZBvhveCZCgPaJlFovlI0ZAhWdWTLxxmJaZCKDG0B8n9VGEvcN3zoS1AHjokSz4aNos39xthp7XtAz9X3NRvp1qU4UTOlxK8IJOC1ApAMmvcEE0kWvgZD"
- FB_TEST_VALID_ACCESS_TOKEN = ""
-
- // remember to change it to a valid signed request to run test
- //FB_TEST_VALID_SIGNED_REQUEST = "ZAxP-ILRQBOwKKxCBMNlGmVraiowV7WFNg761OYBNGc.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEzNDM0OTg0MDAsImlzc3VlZF9hdCI6MTM0MzQ5MzI2NSwib2F1dGhfdG9rZW4iOiJBQUFDWkEzOFpBRDhDb0JBRFpCcmZ5TFpDanBNUVczdThVTWZmRldSWkNpZGw5Tkx4a1BsY2tTcXZaQnpzTW9OWkF2bVk2RUd2NG1hUUFaQ0t2VlpBWkJ5VXA5a0FCU2x6THFJejlvZTdOdHBzdzhyQVpEWkQiLCJ1c2VyIjp7ImNvdW50cnkiOiJ1cyIsImxvY2FsZSI6ImVuX1VTIiwiYWdlIjp7Im1pbiI6MjF9fSwidXNlcl9pZCI6IjUzODc0NDQ2OCJ9"
- FB_TEST_VALID_SIGNED_REQUEST = ""
-
- // test binary file base64 value
- FB_TEST_BINARY_JPG_FILE = "/9j/4AAQSkZJRgABAQEASABIAAD/4gv4SUNDX1BST0ZJTEUAAQEAAAvoAAAAAAIAAABtbnRy" +
- "UkdCIFhZWiAH2QADABsAFQAkAB9hY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAA" +
- "9tYAAQAAAADTLQAAAAAp+D3er/JVrnhC+uTKgzkNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
- "AAAAAAAAABBkZXNjAAABRAAAAHliWFlaAAABwAAAABRiVFJDAAAB1AAACAxkbWRkAAAJ4AAA" +
- "AIhnWFlaAAAKaAAAABRnVFJDAAAB1AAACAxsdW1pAAAKfAAAABRtZWFzAAAKkAAAACRia3B0" +
- "AAAKtAAAABRyWFlaAAAKyAAAABRyVFJDAAAB1AAACAx0ZWNoAAAK3AAAAAx2dWVkAAAK6AAA" +
- "AId3dHB0AAALcAAAABRjcHJ0AAALhAAAADdjaGFkAAALvAAAACxkZXNjAAAAAAAAAB9zUkdC" +
- "IElFQzYxOTY2LTItMSBibGFjayBzY2FsZWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
- "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
- "WFlaIAAAAAAAACSgAAAPhAAAts9jdXJ2AAAAAAAABAAAAAAFAAoADwAUABkAHgAjACgALQAy" +
- "ADcAOwBAAEUASgBPAFQAWQBeAGMAaABtAHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4AsgC3" +
- "ALwAwQDGAMsA0ADVANsA4ADlAOsA8AD2APsBAQEHAQ0BEwEZAR8BJQErATIBOAE+AUUBTAFS" +
- "AVkBYAFnAW4BdQF8AYMBiwGSAZoBoQGpAbEBuQHBAckB0QHZAeEB6QHyAfoCAwIMAhQCHQIm" +
- "Ai8COAJBAksCVAJdAmcCcQJ6AoQCjgKYAqICrAK2AsECywLVAuAC6wL1AwADCwMWAyEDLQM4" +
- "A0MDTwNaA2YDcgN+A4oDlgOiA64DugPHA9MD4APsA/kEBgQTBCAELQQ7BEgEVQRjBHEEfgSM" +
- "BJoEqAS2BMQE0wThBPAE/gUNBRwFKwU6BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYGFgYn" +
- "BjcGSAZZBmoGewaMBp0GrwbABtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgL" +
- "CB8IMghGCFoIbgiCCJYIqgi+CNII5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEKJwo9" +
- "ClQKagqBCpgKrgrFCtwK8wsLCyILOQtRC2kLgAuYC7ALyAvhC/kMEgwqDEMMXAx1DI4MpwzA" +
- "DNkM8w0NDSYNQA1aDXQNjg2pDcMN3g34DhMOLg5JDmQOfw6bDrYO0g7uDwkPJQ9BD14Peg+W" +
- "D7MPzw/sEAkQJhBDEGEQfhCbELkQ1xD1ERMRMRFPEW0RjBGqEckR6BIHEiYSRRJkEoQSoxLD" +
- "EuMTAxMjE0MTYxODE6QTxRPlFAYUJxRJFGoUixStFM4U8BUSFTQVVhV4FZsVvRXgFgMWJhZJ" +
- "FmwWjxayFtYW+hcdF0EXZReJF64X0hf3GBsYQBhlGIoYrxjVGPoZIBlFGWsZkRm3Gd0aBBoq" +
- "GlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMczBz1HR4dRx1wHZkdwx3sHhYeQB5q" +
- "HpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDwIRwhSCF1IaEhziH7IiciVSKCIq8i3SMK" +
- "IzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4JWgllyXHJfcmJyZXJocmtyboJxgnSSd6J6sn3CgN" +
- "KD8ocSiiKNQpBik4KWspnSnQKgIqNSpoKpsqzysCKzYraSudK9EsBSw5LG4soizXLQwtQS12" +
- "Last4S4WLkwugi63Lu4vJC9aL5Evxy/+MDUwbDCkMNsxEjFKMYIxujHyMioyYzKbMtQzDTNG" +
- "M38zuDPxNCs0ZTSeNNg1EzVNNYc1wjX9Njc2cjauNuk3JDdgN5w31zgUOFA4jDjIOQU5Qjl/" +
- "Obw5+To2OnQ6sjrvOy07azuqO+g8JzxlPKQ84z0iPWE9oT3gPiA+YD6gPuA/IT9hP6I/4kAj" +
- "QGRApkDnQSlBakGsQe5CMEJyQrVC90M6Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1" +
- "R3tHwEgFSEtIkUjXSR1JY0mpSfBKN0p9SsRLDEtTS5pL4kwqTHJMuk0CTUpNk03cTiVObk63" +
- "TwBPSU+TT91QJ1BxULtRBlFQUZtR5lIxUnxSx1MTU19TqlP2VEJUj1TbVShVdVXCVg9WXFap" +
- "VvdXRFeSV+BYL1h9WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc1l0nXXhdyV4aXmxevV8P" +
- "X2Ffs2AFYFdgqmD8YU9homH1YklinGLwY0Njl2PrZEBklGTpZT1lkmXnZj1mkmboZz1nk2fp" +
- "aD9olmjsaUNpmmnxakhqn2r3a09rp2v/bFdsr20IbWBtuW4SbmtuxG8eb3hv0XArcIZw4HE6" +
- "cZVx8HJLcqZzAXNdc7h0FHRwdMx1KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5iXnnekZ6pXsE" +
- "e2N7wnwhfIF84X1BfaF+AX5ifsJ/I3+Ef+WAR4CogQqBa4HNgjCCkoL0g1eDuoQdhICE44VH" +
- "hauGDoZyhteHO4efiASIaYjOiTOJmYn+imSKyoswi5aL/IxjjMqNMY2Yjf+OZo7OjzaPnpAG" +
- "kG6Q1pE/kaiSEZJ6kuOTTZO2lCCUipT0lV+VyZY0lp+XCpd1l+CYTJi4mSSZkJn8mmia1ZtC" +
- "m6+cHJyJnPedZJ3SnkCerp8dn4uf+qBpoNihR6G2oiailqMGo3aj5qRWpMelOKWpphqmi6b9" +
- "p26n4KhSqMSpN6mpqhyqj6sCq3Wr6axcrNCtRK24ri2uoa8Wr4uwALB1sOqxYLHWskuywrM4" +
- "s660JbSctRO1irYBtnm28Ldot+C4WbjRuUq5wro7urW7LrunvCG8m70VvY++Cr6Evv+/er/1" +
- "wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XIxkbGw8dBx7/IPci8yTrJuco4yrfLNsu2zDXMtc01" +
- "zbXONs62zzfPuNA50LrRPNG+0j/SwdNE08bUSdTL1U7V0dZV1tjXXNfg2GTY6Nls2fHadtr7" +
- "24DcBdyK3RDdlt4c3qLfKd+v4DbgveFE4cziU+Lb42Pj6+Rz5PzlhOYN5pbnH+ep6DLovOlG" +
- "6dDqW+rl63Dr++yG7RHtnO4o7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD13vZt9vv3ivgZ" +
- "+Kj5OPnH+lf65/t3/Af8mP0p/br+S/7c/23//2Rlc2MAAAAAAAAALklFQyA2MTk2Ni0yLTEg" +
- "RGVmYXVsdCBSR0IgQ29sb3VyIFNwYWNlIC0gc1JHQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
- "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
- "AABYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAAAAAAAAAAAABQAAAAAAAAbWVhcwAAAAAAAAAB" +
- "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACWFlaIAAAAAAAAAMWAAADMwAAAqRYWVogAAAAAAAA" +
- "b6IAADj1AAADkHNpZyAAAAAAQ1JUIGRlc2MAAAAAAAAALVJlZmVyZW5jZSBWaWV3aW5nIENv" +
- "bmRpdGlvbiBpbiBJRUMgNjE5NjYtMi0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
- "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYWVog" +
- "AAAAAAAA9tYAAQAAAADTLXRleHQAAAAAQ29weXJpZ2h0IEludGVybmF0aW9uYWwgQ29sb3Ig" +
- "Q29uc29ydGl1bSwgMjAwOQAAc2YzMgAAAAAAAQxEAAAF3///8yYAAAeUAAD9j///+6H///2i" +
- "AAAD2wAAwHX/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQa" +
- "FRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4e" +
- "Hh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCAAxADIDASIAAhEB" +
- "AxEB/8QAHQAAAQQDAQEAAAAAAAAAAAAAAAUGBwgBAwQJAv/EADYQAAEDAwIEAgcGBwAAAAAA" +
- "AAECAwQABREGIQcSEzFBUQgUIjJhgZEVQnFyobEWIzeFkrLx/8QAGQEBAAMBAQAAAAAAAAAA" +
- "AAAABAECAwUG/8QAKREAAgEDAgQFBQAAAAAAAAAAAAECAxEhBBITMUGBBRQzscEiMlFhcf/a" +
- "AAwDAQACEQMRAD8A23GcGQVdFS2BgPLSfdHiaZnEjWdtslhaehy0rcceCm2G0+1sd1DPbsae" +
- "EvTlylyWnnG5MVbYw44hsHrIIIKVDwG/6VWTXaHJ2qJwiuuyWmXVNoUrJPKk4Hxoiozg1vTX" +
- "YSqkJp7Gmd184namuAS03MSy2kJ91tKlE+ZJFK2iOMGu9OT/AFpq5IlNqQErZksJW2tIOcbA" +
- "EfiDTHi2h1SA6GnNiAsFJwnPY58jQ7Floe6K0FByBvt3pEYJ/bgzluSyXh4N8WbLxEjLjttG" +
- "33lhHO/DWrmCk9ittX3k589xnfzqRDXnroO+TtE8QbVdFKciuw5iA8CO7ROHEkeIKSa9CkLb" +
- "dQl1lYW0sBSFA5CkncH6UiN+oeSszHyorNFSVOt1hooV/KQdj90VRdFmeZ4x6gtcpohaZLx5" +
- "AAAoFfMPwGCk58Kvear3xq0tDsvFWzau6eIl05oM7yC1JPTV8M45f8aPX6N/z5XsJ0rW+wl6" +
- "fYhyz9lyrVDCgA0oNykO4z2CwB7JPfFcz+kXXLq0hNjYmLIKOvIc5W2UeCUoAPN8zTtkQ7PZ" +
- "bJ1oCGmQVJUrlABAGNzj4Ab/AIVmPqQLkSHYBDkVCeo4txPK2CfAKPjQZVat9sVj8noI0YW+" +
- "p5RCPpC6RRbplrnwkIDzmGHEp2ClAeyf3H0q3mj0BrSVnaBJCILKdz5IAqAdfSbc65b7tqRa" +
- "W7e1cI63EkcwS3zjm7fAmpI0nxo0LqPWTWk7C7NfdWFIjyBG5WF8iSSE5PMAAnYkAGmaW6ja" +
- "T5YOP4go8S8VzySTRXzmilnNuKWaS9T2S36gtTtuuLCXWXB2I7HuD9QD8qUqwTUSgpKz5Exk" +
- "4u6K9a0tU+yvvwFOuMpcOGHSkLHnjfYn/tN6FEU6EMTOmpCXAtTjrhUV/AA7AUn+m9qWYNV2" +
- "SwxnXGmokcyiWyQS6okA5HkAfqaj7SOp4lyt5/iCZLPQbPUSl3AOPEgbkGiwpykttzqUta4L" +
- "lkdfEWbF1A1PZVJS1aYLC+rI+6XMYAT54P67VF3D25XDTd4b1FBe9XkRN2XAMnON9j3GNsfG" +
- "tl8v0nUjyYMVr1K0ML5m2UjHNjsVeZ8h4V1x4DK2Exjnp8u/L479hVnTUFh4DTq8WX7LFwPS" +
- "V04qCwqXpy7iQWkl0NcpQF435Sd8ZziioOQEpQlKUAJAwBjsKKr5iRXgIvpWFdqKKaEKVemf" +
- "/Vj+3M/7KqEo3vK/LRRR6XJ9/dm8+nb4HFC7R/yinDA9wfL9qKK01Hpopp/UOs0UUUAWf//Z"
-)
-
-var (
- testGlobalApp = New(FB_TEST_APP_ID, FB_TEST_APP_SECRET)
-)
-
-type AllTypes struct {
- Int int
- Int8 int8
- Int16 int16
- Int32 int32
- Int64 int64
- Uint uint
- Uint8 uint8
- Uint16 uint16
- Uint32 uint32
- Uint64 uint64
- Float32 float32
- Float64 float64
- String string
- ArrayOfInt []int
- MapOfString map[string]string
- NestedStruct *NestedStruct
-}
-
-type NestedStruct struct {
- Int int
- String string
- ArrayOfString []string
-}
-
-type ParamsStruct struct {
- Foo string
- Bar *ParamsNestedStruct
-}
-
-type ParamsNestedStruct struct {
- AAA int
- BBB string
- CCC bool
-}
-
-type FieldTagStruct struct {
- Field1 string `facebook:"field2"`
- Required string `facebook:",required"`
- Foo string `facebook:"bar,required"`
- CanAbsent string
-}
-
-type MessageTag struct {
- Id string
- Name string
- Type string
-}
-
-type MessageTags map[string][]*MessageTag
-
-type NullStruct struct {
- Null *int
-}
-
-func TestApiGetUserInfoV2(t *testing.T) {
- Version = "v2.2"
- defer func() {
- Version = ""
- }()
-
- // It's not allowed to get user info by name. So I get "me" with access token instead.
- if FB_TEST_VALID_ACCESS_TOKEN != "" {
- me, err := Api("me", GET, Params{
- "access_token": FB_TEST_VALID_ACCESS_TOKEN,
- })
-
- if err != nil {
- t.Fatalf("cannot get my info. [e:%v]", err)
- }
-
- if e := me.Err(); e != nil {
- t.Fatalf("facebook returns error. [e:%v]", e)
- }
-
- t.Logf("my info. %v", me)
- }
-}
-
-func TestBatchApiGetInfo(t *testing.T) {
- if FB_TEST_VALID_ACCESS_TOKEN == "" {
- t.Skipf("cannot call batch api without access token. skip this test.")
- }
-
- verifyBatchResult := func(t *testing.T, index int, res Result) {
- batch, err := res.Batch()
-
- if err != nil {
- t.Fatalf("cannot parse batch api results[%v]. [e:%v] [result:%v]", index, err, res)
- }
-
- if batch.StatusCode != 200 {
- t.Fatalf("facebook returns unexpected http status code in results[%v]. [code:%v] [result:%v]", index, batch.StatusCode, res)
- }
-
- contentType := batch.Header.Get("Content-Type")
-
- if contentType == "" {
- t.Fatalf("facebook returns unexpected http header in results[%v]. [header:%v]", index, batch.Header)
- }
-
- if batch.Body == "" {
- t.Fatalf("facebook returns unexpected http body in results[%v]. [body:%v]", index, batch.Body)
- }
-
- var id string
- err = batch.Result.DecodeField("id", &id)
-
- if err != nil {
- t.Fatalf("cannot get 'id' field in results[%v]. [result:%v]", index, res)
- }
-
- if id == "" {
- t.Fatalf("facebook should return account id in results[%v].", index)
- }
- }
-
- test := func(t *testing.T) {
- params1 := Params{
- "method": GET,
- "relative_url": "me",
- }
- params2 := Params{
- "method": GET,
- "relative_url": uint64(100002828925788), // id of my another facebook account
- }
-
- results, err := BatchApi(FB_TEST_VALID_ACCESS_TOKEN, params1, params2)
-
- if err != nil {
- t.Fatalf("cannot get batch result. [e:%v]", err)
- }
-
- if len(results) != 2 {
- t.Fatalf("batch api should return results in an array with 2 entries. [len:%v]", len(results))
- }
-
- if Version == "" {
- t.Log("use default facebook version.")
- } else {
- t.Logf("global facebook version: %v", Version)
- }
-
- for index, result := range results {
- verifyBatchResult(t, index, result)
- }
- }
-
- // Use default Version.
- Version = ""
- test(t)
-
- // User "v2.2".
- Version = "v2.2"
- defer func() {
- Version = ""
- }()
- test(t)
-
- // when providing an invalid access token, BatchApi should return a facebook error.
- _, err := BatchApi("an_invalid_access_token", Params{
- "method": GET,
- "relative_url": "me",
- })
-
- if err == nil {
- t.Fatalf("expect an error when providing an invalid access token to BatchApi.")
- }
-
- if _, ok := err.(*Error); !ok {
- t.Fatalf("batch result error must be an *Error. [e:%v]", err)
- }
-}
-
-func TestApiParseSignedRequest(t *testing.T) {
- if FB_TEST_VALID_SIGNED_REQUEST == "" {
- t.Logf("skip this case as we don't have a valid signed request.")
- return
- }
-
- app := New(FB_TEST_APP_ID, FB_TEST_APP_SECRET)
- res, err := app.ParseSignedRequest(FB_TEST_VALID_SIGNED_REQUEST)
-
- if err != nil {
- t.Fatalf("cannot parse signed request. [e:%v]", err)
- }
-
- t.Logf("signed request is '%v'.", res)
-}
-
-func TestSession(t *testing.T) {
- if FB_TEST_VALID_ACCESS_TOKEN == "" {
- t.Skipf("skip this case as we don't have a valid access token.")
- }
-
- session := &Session{}
- session.SetAccessToken(FB_TEST_VALID_ACCESS_TOKEN)
-
- test := func(t *testing.T, session *Session) {
- id, err := session.User()
-
- if err != nil {
- t.Fatalf("cannot get current user id. [e:%v]", err)
- }
-
- t.Logf("current user id is %v", id)
-
- result, e := session.Api("/me", GET, Params{
- "fields": "id,email,website",
- })
-
- if e != nil {
- t.Fatalf("cannot get my extended info. [e:%v]", e)
- }
-
- if Version == "" {
- t.Log("use default facebook version.")
- } else {
- t.Logf("global facebook version: %v", Version)
- }
-
- if session.Version == "" {
- t.Log("use default session facebook version.")
- } else {
- t.Logf("session facebook version: %v", session.Version)
- }
-
- t.Logf("my extended info is: %v", result)
- }
-
- // Default version.
- test(t, session)
-
- // Global version overwrite default session version.
- func() {
- Version = "v2.2"
- defer func() {
- Version = ""
- }()
-
- test(t, session)
- }()
-
- // Session version overwrite default version.
- func() {
- Version = "vx.y" // an invalid version.
- session.Version = "v2.2"
- defer func() {
- Version = ""
- }()
-
- test(t, session)
- }()
-
- // Session with appsecret proof enabled.
- if FB_TEST_VALID_ACCESS_TOKEN != "" {
- app := New(FB_TEST_APP_ID, FB_TEST_APP_SECRET)
- app.EnableAppsecretProof = true
- session := app.Session(FB_TEST_VALID_ACCESS_TOKEN)
-
- _, e := session.Api("/me", GET, Params{
- "fields": "id",
- })
-
- if e != nil {
- t.Fatalf("cannot get my info with proof. [e:%v]", e)
- }
- }
-}
-
-func TestUploadingBinary(t *testing.T) {
- if FB_TEST_VALID_ACCESS_TOKEN == "" {
- t.Skipf("skip this case as we don't have a valid access token.")
- }
-
- buf := bytes.NewBufferString(FB_TEST_BINARY_JPG_FILE)
- reader := base64.NewDecoder(base64.StdEncoding, buf)
-
- session := &Session{}
- session.SetAccessToken(FB_TEST_VALID_ACCESS_TOKEN)
-
- result, e := session.Api("/me/photos", POST, Params{
- "message": "Test photo from https://github.com/huandu/facebook",
- "source": Data("my_profile.jpg", reader),
- })
-
- if e != nil {
- t.Fatalf("cannot create photo on my timeline. [e:%v]", e)
- }
-
- var id string
- e = result.DecodeField("id", &id)
-
- if e != nil {
- t.Fatalf("facebook should return photo id on success. [e:%v]", e)
- }
-
- t.Logf("newly created photo id is %v", id)
-}
-
-func TestUploadBinaryWithBatch(t *testing.T) {
- if FB_TEST_VALID_ACCESS_TOKEN == "" {
- t.Skipf("skip this case as we don't have a valid access token.")
- }
-
- buf1 := bytes.NewBufferString(FB_TEST_BINARY_JPG_FILE)
- reader1 := base64.NewDecoder(base64.StdEncoding, buf1)
- buf2 := bytes.NewBufferString(FB_TEST_BINARY_JPG_FILE)
- reader2 := base64.NewDecoder(base64.StdEncoding, buf2)
-
- session := &Session{}
- session.SetAccessToken(FB_TEST_VALID_ACCESS_TOKEN)
-
- // sample comes from facebook batch api sample.
- // https://developers.facebook.com/docs/reference/api/batch/
- //
- // curl
- // -F 'access_token=…' \
- // -F 'batch=[{"method":"POST","relative_url":"me/photos","body":"message=My cat photo","attached_files":"file1"},{"method":"POST","relative_url":"me/photos","body":"message=My dog photo","attached_files":"file2"},]' \
- // -F 'file1=@cat.gif' \
- // -F 'file2=@dog.jpg' \
- // https://graph.facebook.com
- result, e := session.Batch(Params{
- "file1": Data("cat.jpg", reader1),
- "file2": Data("dog.jpg", reader2),
- }, Params{
- "method": POST,
- "relative_url": "me/photos",
- "body": "message=My cat photo",
- "attached_files": "file1",
- }, Params{
- "method": POST,
- "relative_url": "me/photos",
- "body": "message=My dog photo",
- "attached_files": "file2",
- })
-
- if e != nil {
- t.Fatalf("cannot create photo on my timeline. [e:%v]", e)
- }
-
- t.Logf("batch call result. [result:%v]", result)
-}
-
-func TestSimpleFQL(t *testing.T) {
- defer func() {
- Version = ""
- }()
-
- test := func(t *testing.T, session *Session) {
- me, err := session.FQL("SELECT name FROM user WHERE uid = 538744468")
-
- if err != nil {
- t.Fatalf("cannot get my info. [e:%v]", err)
- }
-
- if len(me) != 1 {
- t.Fatalf("expect to get only 1 result. [len:%v]", len(me))
- }
-
- t.Logf("my name. %v", me[0]["name"])
- }
-
- // v2.2 api doesn't allow me to query user without access token.
- if FB_TEST_VALID_ACCESS_TOKEN == "" {
- return
- }
-
- Version = "v2.2"
- session := &Session{}
- session.SetAccessToken(FB_TEST_VALID_ACCESS_TOKEN)
- test(t, session)
-}
-
-func TestMultiFQL(t *testing.T) {
- defer func() {
- Version = ""
- }()
-
- test := func(t *testing.T, session *Session) {
- res, err := session.MultiFQL(Params{
- "query1": "SELECT username FROM page WHERE page_id = 20531316728",
- "query2": "SELECT uid FROM user WHERE uid = 538744468",
- })
-
- if err != nil {
- t.Fatalf("cannot get my info. [e:%v]", err)
- }
-
- if err = res.Err(); err != nil {
- t.Fatalf("fail to parse facebook api error. [e:%v]", err)
- }
-
- var query1, query2 []Result
-
- err = res.DecodeField("query1", &query1)
-
- if err != nil {
- t.Fatalf("cannot get result of query1. [e:%v]", err)
- }
-
- if len(query1) != 1 {
- t.Fatalf("expect to get only 1 result in query1. [len:%v]", len(query1))
- }
-
- err = res.DecodeField("query2", &query2)
-
- if err != nil {
- t.Fatalf("cannot get result of query2. [e:%v]", err)
- }
-
- if len(query2) != 1 {
- t.Fatalf("expect to get only 1 result in query2. [len:%v]", len(query2))
- }
-
- var username string
- var uid string
-
- err = query1[0].DecodeField("username", &username)
-
- if err != nil {
- t.Fatalf("cannot decode username from query1. [e:%v]", err)
- }
-
- if username != "facebook" {
- t.Fatalf("username is expected to be 'facebook'. [username:%v]", username)
- }
-
- err = query2[0].DecodeField("uid", &uid)
-
- if err != nil {
- t.Fatalf("cannot decode username from query2. [e:%v] [query2:%v]", err, query2)
- }
-
- if uid != "538744468" {
- t.Fatalf("username is expected to be 'facebook'. [username:%v]", username)
- }
- }
-
- // v2.2 api doesn't allow me to query user without access token.
- if FB_TEST_VALID_ACCESS_TOKEN == "" {
- return
- }
-
- Version = "v2.2"
- session := &Session{}
- session.SetAccessToken(FB_TEST_VALID_ACCESS_TOKEN)
- test(t, session)
-}
-
-func TestGraphDebuggingAPI(t *testing.T) {
- if FB_TEST_VALID_ACCESS_TOKEN == "" {
- t.Skipf("cannot call batch api without access token. skip this test.")
- }
-
- test := func(t *testing.T, session *Session) {
- session.SetAccessToken(FB_TEST_VALID_ACCESS_TOKEN)
- defer session.SetAccessToken("")
-
- // test app must not grant "read_friendlists" permission.
- // otherwise there is no way to get a warning from facebook.
- res, _ := session.Get("/me/friendlists", nil)
-
- if res == nil {
- t.Fatalf("res must not be nil.")
- }
-
- debugInfo := res.DebugInfo()
-
- if debugInfo == nil {
- t.Fatalf("debug info must exist.")
- }
-
- t.Logf("facebook response is: %v", res)
- t.Logf("debug info is: %v", *debugInfo)
-
- if debugInfo.Messages == nil && len(debugInfo.Messages) > 0 {
- t.Fatalf("facebook must warn me for the permission issue.")
- }
-
- msg := debugInfo.Messages[0]
-
- if msg.Type == "" || msg.Message == "" {
- t.Fatalf("facebook must say something. [msg:%v]", msg)
- }
-
- if debugInfo.FacebookApiVersion == "" {
- t.Fatalf("facebook must tell me api version.")
- }
-
- if debugInfo.FacebookDebug == "" {
- t.Fatalf("facebook must tell me X-FB-Debug.")
- }
-
- if debugInfo.FacebookRev == "" {
- t.Fatalf("facebook must tell me x-fb-rev.")
- }
- }
-
- defer func() {
- Debug = DEBUG_OFF
- Version = ""
- }()
-
- Version = "v2.2"
- Debug = DEBUG_ALL
- test(t, defaultSession)
- session := &Session{}
- session.SetDebug(DEBUG_ALL)
- test(t, session)
-
- // test changing debug mode.
- old := session.SetDebug(DEBUG_OFF)
-
- if old != DEBUG_ALL {
- t.Fatalf("debug mode must be DEBUG_ALL. [debug:%v]", old)
- }
-
- if session.Debug() != DEBUG_ALL {
- t.Fatalf("debug mode must be DEBUG_ALL [debug:%v]", session.Debug())
- }
-
- Debug = DEBUG_OFF
-
- if session.Debug() != DEBUG_OFF {
- t.Fatalf("debug mode must be DEBUG_OFF. [debug:%v]", session.Debug())
- }
-}
-
-func TestResultDecode(t *testing.T) {
- strNormal := `{
- "int": 1234,
- "int8": 23,
- "int16": 12345,
- "int32": -127372843,
- "int64": 192438483489298,
- "uint": 1283829,
- "uint8": 233,
- "uint16": 62121,
- "uint32": 3083747392,
- "uint64": 2034857382993849,
- "float32": 9382.38429,
- "float64": 3984.293848292,
- "map_of_string": {"a": "1", "b": "2"},
- "array_of_int": [12, 34, 56],
- "string": "abcd",
- "notused": 1234,
- "nested_struct": {
- "string": "hello",
- "int": 123,
- "array_of_string": ["a", "b", "c"]
- }
- }`
- strOverflow := `{
- "int": 1234,
- "int8": 23,
- "int16": 12345,
- "int32": -127372843,
- "int64": 192438483489298,
- "uint": 1283829,
- "uint8": 233,
- "uint16": 62121,
- "uint32": 383083747392,
- "uint64": 2034857382993849,
- "float32": 9382.38429,
- "float64": 3984.293848292,
- "string": "abcd",
- "map_of_string": {"a": "1", "b": "2"},
- "array_of_int": [12, 34, 56],
- "string": "abcd",
- "notused": 1234,
- "nested_struct": {
- "string": "hello",
- "int": 123,
- "array_of_string": ["a", "b", "c"]
- }
- }`
- strMissAField := `{
- "int": 1234,
- "int8": 23,
- "int16": 12345,
- "int32": -127372843,
-
- "missed": "int64",
-
- "uint": 1283829,
- "uint8": 233,
- "uint16": 62121,
- "uint32": 383083747392,
- "uint64": 2034857382993849,
- "float32": 9382.38429,
- "float64": 3984.293848292,
- "string": "abcd",
- "map_of_string": {"a": "1", "b": "2"},
- "array_of_int": [12, 34, 56],
- "string": "abcd",
- "notused": 1234,
- "nested_struct": {
- "string": "hello",
- "int": 123,
- "array_of_string": ["a", "b", "c"]
- }
- }`
- var result Result
- var err error
- var normal, withError AllTypes
- var anInt int
-
- err = json.Unmarshal([]byte(strNormal), &result)
-
- if err != nil {
- t.Fatalf("cannot unmarshal json string. [e:%v]", err)
- }
-
- err = result.Decode(&normal)
-
- if err != nil {
- t.Fatalf("cannot decode normal struct. [e:%v]", err)
- }
-
- err = json.Unmarshal([]byte(strOverflow), &result)
-
- if err != nil {
- t.Fatalf("cannot unmarshal json string. [e:%v]", err)
- }
-
- err = result.Decode(&withError)
-
- if err == nil {
- t.Fatalf("struct should be overflow")
- }
-
- t.Logf("overflow struct. e:%v", err)
-
- err = json.Unmarshal([]byte(strMissAField), &result)
-
- if err != nil {
- t.Fatalf("cannot unmarshal json string. [e:%v]", err)
- }
-
- err = result.Decode(&withError)
-
- if err == nil {
- t.Fatalf("a field in struct should absent in json map.")
- }
-
- t.Logf("miss-a-field struct. e:%v", err)
-
- err = result.DecodeField("array_of_int.2", &anInt)
-
- if err != nil {
- t.Fatalf("cannot decode array item. [e:%v]", err)
- }
-
- if anInt != 56 {
- t.Fatalf("invalid array value. expected 56, actual %v", anInt)
- }
-
- err = result.DecodeField("nested_struct.int", &anInt)
-
- if err != nil {
- t.Fatalf("cannot decode nested struct item. [e:%v]", err)
- }
-
- if anInt != 123 {
- t.Fatalf("invalid array value. expected 123, actual %v", anInt)
- }
-}
-
-func TestParamsEncode(t *testing.T) {
- var params Params
- buf := &bytes.Buffer{}
-
- if mime, err := params.Encode(buf); err != nil || mime != _MIME_FORM_URLENCODED || buf.Len() != 0 {
- t.Fatalf("empty params must encode to an empty string. actual is [e:%v] [str:%v] [mime:%v]", err, buf.String(), mime)
- }
-
- buf.Reset()
- params = Params{}
- params["need_escape"] = "&=+"
- expectedEncoding := "need_escape=%26%3D%2B"
-
- if mime, err := params.Encode(buf); err != nil || mime != _MIME_FORM_URLENCODED || buf.String() != expectedEncoding {
- t.Fatalf("wrong params encode result. expected is '%v'. actual is '%v'. [e:%v] [mime:%v]", expectedEncoding, buf.String(), err, mime)
- }
-
- buf.Reset()
- data := ParamsStruct{
- Foo: "hello, world!",
- Bar: &ParamsNestedStruct{
- AAA: 1234,
- BBB: "bbb",
- CCC: true,
- },
- }
- params = MakeParams(data)
- /* there is no easy way to compare two encoded maps. so i just write expect map here, not test it.
- expectedParams := Params{
- "foo": "hello, world!",
- "bar": map[string]interface{}{
- "aaa": 1234,
- "bbb": "bbb",
- "ccc": true,
- },
- }
- */
-
- if params == nil {
- t.Fatalf("make params error.")
- }
-
- mime, err := params.Encode(buf)
- t.Logf("complex encode result is '%v'. [e:%v] [mime:%v]", buf.String(), err, mime)
-}
-
-func TestStructFieldTag(t *testing.T) {
- strNormalField := `{
- "field2": "hey",
- "required": "my",
- "bar": "dear"
- }`
- strMissingField2Field := `{
- "field1": "hey",
- "required": "my",
- "bar": "dear"
- }`
- strMissingRequiredField := `{
- "field1": "hey",
- "bar": "dear",
- "can_absent": "babe"
- }`
- strMissingBarField := `{
- "field1": "hey",
- "required": "my"
- }`
-
- var result Result
- var value FieldTagStruct
- var err error
-
- err = json.Unmarshal([]byte(strNormalField), &result)
-
- if err != nil {
- t.Fatalf("cannot unmarshal json string. [e:%v]", err)
- }
-
- err = result.Decode(&value)
-
- if err != nil {
- t.Fatalf("cannot decode struct. [e:%v]", err)
- }
-
- result = Result{}
- value = FieldTagStruct{}
- err = json.Unmarshal([]byte(strMissingField2Field), &result)
-
- if err != nil {
- t.Fatalf("cannot unmarshal json string. [e:%v]", err)
- }
-
- err = result.Decode(&value)
-
- if err != nil {
- t.Fatalf("cannot decode struct. [e:%v]", err)
- }
-
- if value.Field1 != "" {
- t.Fatalf("value field1 should be kept unchanged. [field1:%v]", value.Field1)
- }
-
- result = Result{}
- value = FieldTagStruct{}
- err = json.Unmarshal([]byte(strMissingRequiredField), &result)
-
- if err != nil {
- t.Fatalf("cannot unmarshal json string. [e:%v]", err)
- }
-
- err = result.Decode(&value)
-
- if err == nil {
- t.Fatalf("should fail to decode struct.")
- }
-
- t.Logf("expected decode error. [e:%v]", err)
-
- result = Result{}
- value = FieldTagStruct{}
- err = json.Unmarshal([]byte(strMissingBarField), &result)
-
- if err != nil {
- t.Fatalf("cannot unmarshal json string. [e:%v]", err)
- }
-
- err = result.Decode(&value)
-
- if err == nil {
- t.Fatalf("should fail to decode struct.")
- }
-
- t.Logf("expected decode error. [e:%v]", err)
-}
-
-type myTime time.Time
-
-func TestDecodeField(t *testing.T) {
- jsonStr := `{
- "int": 1234,
- "array": ["abcd", "efgh"],
- "map": {
- "key1": 5678,
- "nested_map": {
- "key2": "ijkl",
- "key3": [{
- "key4": "mnop"
- }, {
- "key5": 9012
- }]
- }
- },
- "message_tags": {
- "2": [
- {
- "id": "4838901",
- "name": "Foo Bar",
- "type": "page"
- },
- {
- "id": "293450302",
- "name": "Player Rocks",
- "type": "page"
- }
- ]
- },
- "nullStruct": {
- "null": null
- },
- "timestamp": "2015-01-03T11:15:01+0000",
- "custom_timestamp": "2014-03-04T11:15:01+0000"
- }`
-
- var result Result
- var err error
- var anInt int
- var aString string
- var aSlice []string
- var subResults []Result
- var aNull NullStruct = NullStruct{
- Null: &anInt,
- }
- var aTimestamp time.Time
- var aCustomTimestamp myTime
-
- err = json.Unmarshal([]byte(jsonStr), &result)
-
- if err != nil {
- t.Fatalf("invalid json string. [e:%v]", err)
- }
-
- err = result.DecodeField("int", &anInt)
-
- if err != nil {
- t.Fatalf("cannot decode int field. [e:%v]", err)
- }
-
- if anInt != 1234 {
- t.Fatalf("expected int value is 1234. [int:%v]", anInt)
- }
-
- err = result.DecodeField("array.0", &aString)
-
- if err != nil {
- t.Fatalf("cannot decode array.0 field. [e:%v]", err)
- }
-
- if aString != "abcd" {
- t.Fatalf("expected array.0 value is 'abcd'. [string:%v]", aString)
- }
-
- err = result.DecodeField("array.1", &aString)
-
- if err != nil {
- t.Fatalf("cannot decode array.1 field. [e:%v]", err)
- }
-
- if aString != "efgh" {
- t.Fatalf("expected array.1 value is 'abcd'. [string:%v]", aString)
- }
-
- err = result.DecodeField("array.2", &aString)
-
- if err == nil {
- t.Fatalf("array.2 doesn't exist. expect an error.")
- }
-
- err = result.DecodeField("map.key1", &anInt)
-
- if err != nil {
- t.Fatalf("cannot decode map.key1 field. [e:%v]", err)
- }
-
- if anInt != 5678 {
- t.Fatalf("expected map.key1 value is 5678. [int:%v]", anInt)
- }
-
- err = result.DecodeField("map.nested_map.key2", &aString)
-
- if err != nil {
- t.Fatalf("cannot decode map.nested_map.key2 field. [e:%v]", err)
- }
-
- if aString != "ijkl" {
- t.Fatalf("expected map.nested_map.key2 value is 'ijkl'. [string:%v]", aString)
- }
-
- err = result.DecodeField("array", &aSlice)
-
- if err != nil {
- t.Fatalf("cannot decode array field. [e:%v]", err)
- }
-
- if len(aSlice) != 2 || aSlice[0] != "abcd" || aSlice[1] != "efgh" {
- t.Fatalf("expected array value is ['abcd', 'efgh']. [slice:%v]", aSlice)
- }
-
- err = result.DecodeField("map.nested_map.key3", &subResults)
-
- if err != nil {
- t.Fatalf("cannot decode map.nested_map.key3 field. [e:%v]", err)
- }
-
- if len(subResults) != 2 {
- t.Fatalf("expected sub results len is 2. [len:%v] [results:%v]", subResults)
- }
-
- err = subResults[0].DecodeField("key4", &aString)
-
- if err != nil {
- t.Fatalf("cannot decode key4 field in sub result. [e:%v]", err)
- }
-
- if aString != "mnop" {
- t.Fatalf("expected map.nested_map.key2 value is 'mnop'. [string:%v]", aString)
- }
-
- err = subResults[1].DecodeField("key5", &anInt)
-
- if err != nil {
- t.Fatalf("cannot decode key5 field. [e:%v]", err)
- }
-
- if anInt != 9012 {
- t.Fatalf("expected key5 value is 9012. [int:%v]", anInt)
- }
-
- err = result.DecodeField("message_tags.2.0.id", &aString)
-
- if err != nil {
- t.Fatalf("cannot decode message_tags.2.0.id field. [e:%v]", err)
- }
-
- if aString != "4838901" {
- t.Fatalf("expected message_tags.2.0.id value is '4838901'. [string:%v]", aString)
- }
-
- var messageTags MessageTags
- err = result.DecodeField("message_tags", &messageTags)
-
- if err != nil {
- t.Fatalf("cannot decode message_tags field. [e:%v]", err)
- }
-
- if len(messageTags) != 1 {
- t.Fatalf("expect messageTags have only 1 element. [len:%v]", len(messageTags))
- }
-
- aString = messageTags["2"][1].Id
-
- if aString != "293450302" {
- t.Fatalf("expect messageTags.2.1.id value is '293450302'. [value:%v]", aString)
- }
-
- err = result.DecodeField("nullStruct", &aNull)
-
- if err != nil {
- t.Fatalf("cannot decode nullStruct field. [e:%v]", err)
- }
-
- if aNull.Null != nil {
- t.Fatalf("expect aNull.Null is reset to nil.")
- }
-
- err = result.DecodeField("timestamp", &aTimestamp)
-
- if err != nil {
- t.Fatalf("cannot decode timestamp field. [e:%v]", err)
- }
-
- if !aTimestamp.Equal(time.Date(2015, time.January, 3, 11, 15, 1, 0, time.FixedZone("no-offset", 0))) {
- t.Fatalf("expect aTimestamp date to be 2015-01-03 11:15:01 +0000 [value:%v]", aTimestamp.String())
- }
-
- err = result.DecodeField("custom_timestamp", &aCustomTimestamp)
-
- if err != nil {
- t.Fatalf("cannot decode custom_timestamp field. [e:%v]", err)
- }
-
- if !time.Time(aCustomTimestamp).Equal(time.Date(2014, time.March, 4, 11, 15, 1, 0, time.FixedZone("no-offset", 0))) {
- t.Fatalf("expect aCustomTimestamp date to be 2014-03-04 11:15:01 +0000 [value:%v]", time.Time(aCustomTimestamp).String())
- }
-}
-
-func TestGraphError(t *testing.T) {
- res, err := Get("/me", Params{
- "access_token": "fake",
- })
-
- if err == nil {
- t.Fatalf("facebook should return error for bad access token. [res:%v]", res)
- }
-
- fbErr, ok := err.(*Error)
-
- if !ok {
- t.Fatalf("error must be a *Error. [e:%v]", err)
- }
-
- t.Logf("facebook error. [e:%v] [message:%v] [type:%v] [code:%v] [subcode:%v]", err, fbErr.Message, fbErr.Type, fbErr.Code, fbErr.ErrorSubcode)
-}
-
-type FacebookFriend struct {
- Id string `facebook:",required"`
- Name string `facebook:",required"`
-}
-
-type FacebookFriends struct {
- Friends []FacebookFriend `facebook:"data,required"`
-}
-
-func TestPagingResultDecode(t *testing.T) {
- res := Result{
- "data": []interface{}{
- map[string]interface{}{
- "name": "friend 1",
- "id": "1",
- },
- map[string]interface{}{
- "name": "friend 2",
- "id": "2",
- },
- },
- "paging": map[string]interface{}{
- "next": "https://graph.facebook.com/...",
- },
- }
- paging, err := newPagingResult(nil, res)
- if err != nil {
- t.Fatalf("cannot create paging result. [e:%v]", err)
- }
- var friends FacebookFriends
- if err := paging.Decode(&friends); err != nil {
- t.Fatalf("cannot decode paging result. [e:%v]", err)
- }
- if len(friends.Friends) != 2 {
- t.Fatalf("expect to have 2 friends. [len:%v]", len(friends.Friends))
- }
- if friends.Friends[0].Name != "friend 1" {
- t.Fatalf("expect name to be 'friend 1'. [name:%v]", friends.Friends[0].Name)
- }
- if friends.Friends[0].Id != "1" {
- t.Fatalf("expect id to be '1'. [id:%v]", friends.Friends[0].Id)
- }
- if friends.Friends[1].Name != "friend 2" {
- t.Fatalf("expect name to be 'friend 2'. [name:%v]", friends.Friends[1].Name)
- }
- if friends.Friends[1].Id != "2" {
- t.Fatalf("expect id to be '2'. [id:%v]", friends.Friends[1].Id)
- }
-}
-
-func TestPagingResult(t *testing.T) {
- if FB_TEST_VALID_ACCESS_TOKEN == "" {
- t.Skipf("skip this case as we don't have a valid access token.")
- }
-
- session := &Session{}
- session.SetAccessToken(FB_TEST_VALID_ACCESS_TOKEN)
- res, err := session.Get("/me/home", Params{
- "limit": 2,
- })
-
- if err != nil {
- t.Fatalf("cannot get my home post. [e:%v]", err)
- }
-
- paging, err := res.Paging(session)
-
- if err != nil {
- t.Fatalf("cannot get paging information. [e:%v]", err)
- }
-
- data := paging.Data()
-
- if len(data) != 2 {
- t.Fatalf("expect to have only 2 post. [len:%v]", len(data))
- }
-
- t.Logf("result: %v", res)
- t.Logf("previous: %v", paging.previous)
-
- noMore, err := paging.Previous()
-
- if err != nil {
- t.Fatalf("cannot get paging information. [e:%v]", err)
- }
-
- if !noMore {
- t.Fatalf("should have no more post. %v", *paging.paging.Paging)
- }
-
- noMore, err = paging.Next()
-
- if err != nil {
- t.Fatalf("cannot get paging information. [e:%v]", err)
- }
-
- data = paging.Data()
-
- if len(data) != 2 {
- t.Fatalf("expect to have only 2 post. [len:%v]", len(data))
- }
-
- noMore, err = paging.Next()
-
- if err != nil {
- t.Fatalf("cannot get paging information. [e:%v]", err)
- }
-
- if len(paging.Data()) != 2 {
- t.Fatalf("expect to have only 2 post. [len:%v]", len(paging.Data()))
- }
-}
-
-func TestDecodeLargeInteger(t *testing.T) {
- bigIntegers := []int64{
- 1<<53 - 2,
- 1<<53 - 1,
- 1 << 53,
- 1<<53 + 1,
- 1<<53 + 2,
-
- 1<<54 - 2,
- 1<<54 - 1,
- 1 << 54,
- 1<<54 + 1,
- 1<<54 + 2,
-
- 1<<60 - 2,
- 1<<60 - 1,
- 1 << 60,
- 1<<60 + 1,
- 1<<60 + 2,
-
- 1<<63 - 2,
- 1<<63 - 1,
-
- -(1<<53 - 2),
- -(1<<53 - 1),
- -(1 << 53),
- -(1<<53 + 1),
- -(1<<53 + 2),
-
- -(1<<54 - 2),
- -(1<<54 - 1),
- -(1 << 54),
- -(1<<54 + 1),
- -(1<<54 + 2),
-
- -(1<<60 - 2),
- -(1<<60 - 1),
- -(1 << 60),
- -(1<<60 + 1),
- -(1<<60 + 2),
-
- -(1<<53 - 2),
- -(1<<63 - 1),
- -(1 << 63),
- }
- jsonStr := `{
- "integers": [%v]
- }`
-
- buf := &bytes.Buffer{}
-
- for _, v := range bigIntegers {
- buf.WriteString(fmt.Sprintf("%v", v))
- buf.WriteRune(',')
- }
-
- buf.WriteRune('0')
- json := fmt.Sprintf(jsonStr, buf.String())
-
- res, err := MakeResult([]byte(json))
-
- if err != nil {
- t.Fatalf("cannot make result on test json string. [e:%v]", err)
- }
-
- var actualIntegers []int64
- err = res.DecodeField("integers", &actualIntegers)
-
- if err != nil {
- t.Fatalf("cannot decode integers from json. [e:%v]", err)
- }
-
- if len(actualIntegers) != len(bigIntegers)+1 {
- t.Fatalf("count of decoded integers is not correct. [expected:%v] [actual:%v]", len(bigIntegers)+1, len(actualIntegers))
- }
-
- for k, _ := range bigIntegers {
- if bigIntegers[k] != actualIntegers[k] {
- t.Logf("expected integers: %v", bigIntegers)
- t.Logf("actual integers: %v", actualIntegers)
- t.Fatalf("a decoded integer is not expected. [expected:%v] [actual:%v]", bigIntegers[k], actualIntegers[k])
- }
- }
-}
-
-func TestInspectValidToken(t *testing.T) {
- if FB_TEST_VALID_ACCESS_TOKEN == "" {
- t.Skipf("skip this case as we don't have a valid access token.")
- }
-
- session := testGlobalApp.Session(FB_TEST_VALID_ACCESS_TOKEN)
- result, err := session.Inspect()
-
- if err != nil {
- t.Fatalf("cannot inspect a valid access token. [e:%v]", err)
- }
-
- var isValid bool
- err = result.DecodeField("is_valid", &isValid)
-
- if err != nil {
- t.Fatalf("cannot get 'is_valid' in inspect result. [e:%v]", err)
- }
-
- if !isValid {
- t.Fatalf("inspect result shows access token is invalid. why? [result:%v]", result)
- }
-}
-
-func TestInspectInvalidToken(t *testing.T) {
- invalidToken := "CAACZA38ZAD8CoBAe2bDC6EdThnni3b56scyshKINjZARoC9ZAuEUTgYUkYnKdimqfA2ZAXcd2wLd7Rr8jLmMXTY9vqAhQGqObZBIUz1WwbqVoCsB3AAvLtwoWNhsxM76mK0eiJSLXHZCdPVpyhmtojvzXA7f69Bm6b5WZBBXia8iOpPZAUHTGp1UQLFMt47c7RqJTrYIl3VfAR0deN82GMFL2"
- session := testGlobalApp.Session(invalidToken)
- result, err := session.Inspect()
-
- if err == nil {
- t.Fatalf("facebook should indicate it's an invalid token. why not? [result:%v]", result)
- }
-
- if _, ok := err.(*Error); !ok {
- t.Fatalf("inspect error should be a standard facebook error. why not? [e:%v]", err)
- }
-
- isValid := true
- err = result.DecodeField("is_valid", &isValid)
-
- if err != nil {
- t.Fatalf("cannot get 'is_valid' in inspect result. [e:%v]", err)
- }
-
- if isValid {
- t.Fatalf("inspect result shows access token is valid. why? [result:%v]", result)
- }
-}
-
-func TestCamelCaseToUnderScore(t *testing.T) {
- cases := map[string]string{
- "TestCase": "test_case",
- "HTTPServer": "http_server",
- "NoHTTPS": "no_https",
- "Wi_thF": "wi_th_f",
- "_AnotherTES_TCaseP": "_another_tes_t_case_p",
- "ALL": "all",
- "UserID": "user_id",
- }
-
- for k, v := range cases {
- str := camelCaseToUnderScore(k)
-
- if str != v {
- t.Fatalf("wrong underscore string. [expect:%v] [actual:%v]", v, str)
- }
- }
-}
-
-func TestMakeSliceResult(t *testing.T) {
- jsonStr := `{
- "error": {
- "message": "Invalid OAuth access token.",
- "type": "OAuthException",
- "code": 190
- }
- }`
- var res []Result
- err := makeResult([]byte(jsonStr), &res)
-
- if err == nil {
- t.Fatalf("makeResult must fail")
- }
-
- fbErr, ok := err.(*Error)
-
- if !ok {
- t.Fatalf("error must be a facebook error. [e:%v]", err)
- }
-
- if fbErr.Code != 190 {
- t.Fatalf("invalid facebook error. [e:%v]", fbErr.Error())
- }
-}
-
-func TestMakeSliceResultWithNilElements(t *testing.T) {
- jsonStr := `[
- null,
- {
- "foo": "bar"
- },
- null
- ]`
- var res []Result
- err := makeResult([]byte(jsonStr), &res)
-
- if err != nil {
- t.Fatalf("fail to decode results. [e:%v]", err)
- }
-
- if len(res) != 3 {
- t.Fatalf("expect 3 elements in res. [res:%v]", res)
- }
-
- if res[0] != nil || res[1] == nil || res[2] != nil {
- t.Fatalf("decoded res is not expected. [res:%v]", res)
- }
-
- if res[1]["foo"].(string) != "bar" {
- t.Fatalf("decode res is not expected. [res:%v]", res)
- }
-}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/misc.go b/Godeps/_workspace/src/github.com/huandu/facebook/misc.go
deleted file mode 100644
index cdf7a9577..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/misc.go
+++ /dev/null
@@ -1,131 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "bytes"
- "io"
- "unicode"
- "unicode/utf8"
-)
-
-func camelCaseToUnderScore(str string) string {
- if len(str) == 0 {
- return ""
- }
-
- buf := &bytes.Buffer{}
- var prev, r0, r1 rune
- var size int
-
- r0 = '_'
-
- for len(str) > 0 {
- prev = r0
- r0, size = utf8.DecodeRuneInString(str)
- str = str[size:]
-
- switch {
- case r0 == utf8.RuneError:
- buf.WriteByte(byte(str[0]))
-
- case unicode.IsUpper(r0):
- if prev != '_' {
- buf.WriteRune('_')
- }
-
- buf.WriteRune(unicode.ToLower(r0))
-
- if len(str) == 0 {
- break
- }
-
- r0, size = utf8.DecodeRuneInString(str)
- str = str[size:]
-
- if !unicode.IsUpper(r0) {
- buf.WriteRune(r0)
- break
- }
-
- // find next non-upper-case character and insert `_` properly.
- // it's designed to convert `HTTPServer` to `http_server`.
- // if there are more than 2 adjacent upper case characters in a word,
- // treat them as an abbreviation plus a normal word.
- for len(str) > 0 {
- r1 = r0
- r0, size = utf8.DecodeRuneInString(str)
- str = str[size:]
-
- if r0 == utf8.RuneError {
- buf.WriteRune(unicode.ToLower(r1))
- buf.WriteByte(byte(str[0]))
- break
- }
-
- if !unicode.IsUpper(r0) {
- if r0 == '_' || r0 == ' ' || r0 == '-' {
- r0 = '_'
-
- buf.WriteRune(unicode.ToLower(r1))
- } else {
- buf.WriteRune('_')
- buf.WriteRune(unicode.ToLower(r1))
- buf.WriteRune(r0)
- }
-
- break
- }
-
- buf.WriteRune(unicode.ToLower(r1))
- }
-
- if len(str) == 0 || r0 == '_' {
- buf.WriteRune(unicode.ToLower(r0))
- break
- }
-
- default:
- if r0 == ' ' || r0 == '-' {
- r0 = '_'
- }
-
- buf.WriteRune(r0)
- }
- }
-
- return buf.String()
-}
-
-// Returns error string.
-func (e *Error) Error() string {
- return e.Message
-}
-
-// Creates a new binary data holder.
-func Data(filename string, source io.Reader) *binaryData {
- return &binaryData{
- Filename: filename,
- Source: source,
- }
-}
-
-// Creates a binary file holder.
-func File(filename, path string) *binaryFile {
- return &binaryFile{
- Filename: filename,
- }
-}
-
-// Creates a binary file holder and specific a different path for reading.
-func FileAlias(filename, path string) *binaryFile {
- return &binaryFile{
- Filename: filename,
- Path: path,
- }
-}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/paging_result.go b/Godeps/_workspace/src/github.com/huandu/facebook/paging_result.go
deleted file mode 100644
index f1eb9b7f1..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/paging_result.go
+++ /dev/null
@@ -1,146 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "bytes"
- "fmt"
- "net/http"
-)
-
-type pagingData struct {
- Data []Result `facebook:",required"`
- Paging *pagingNavigator
-}
-
-type pagingNavigator struct {
- Previous string
- Next string
-}
-
-func newPagingResult(session *Session, res Result) (*PagingResult, error) {
- // quick check whether Result is a paging response.
- if _, ok := res["data"]; !ok {
- return nil, fmt.Errorf("current Result is not a paging response.")
- }
-
- pr := &PagingResult{
- session: session,
- }
- paging := &pr.paging
- err := res.Decode(paging)
-
- if err != nil {
- return nil, err
- }
-
- if paging.Paging != nil {
- pr.previous = paging.Paging.Previous
- pr.next = paging.Paging.Next
- }
-
- return pr, nil
-}
-
-// Get current data.
-func (pr *PagingResult) Data() []Result {
- return pr.paging.Data
-}
-
-// Decodes the current full result to a struct. See Result#Decode.
-func (pr *PagingResult) Decode(v interface{}) (err error) {
- res := Result{
- "data": pr.Data(),
- }
- return res.Decode(v)
-}
-
-// Read previous page.
-func (pr *PagingResult) Previous() (noMore bool, err error) {
- if !pr.HasPrevious() {
- noMore = true
- return
- }
-
- return pr.navigate(&pr.previous)
-}
-
-// Read next page.
-func (pr *PagingResult) Next() (noMore bool, err error) {
- if !pr.HasNext() {
- noMore = true
- return
- }
-
- return pr.navigate(&pr.next)
-}
-
-// Check whether there is previous page.
-func (pr *PagingResult) HasPrevious() bool {
- return pr.previous != ""
-}
-
-// Check whether there is next page.
-func (pr *PagingResult) HasNext() bool {
- return pr.next != ""
-}
-
-func (pr *PagingResult) navigate(url *string) (noMore bool, err error) {
- var pagingUrl string
-
- // add session information in paging url.
- params := Params{}
- pr.session.prepareParams(params)
-
- if len(params) == 0 {
- pagingUrl = *url
- } else {
- buf := &bytes.Buffer{}
- buf.WriteString(*url)
- buf.WriteRune('&')
- params.Encode(buf)
-
- pagingUrl = buf.String()
- }
-
- var request *http.Request
- var res Result
-
- request, err = http.NewRequest("GET", pagingUrl, nil)
-
- if err != nil {
- return
- }
-
- res, err = pr.session.Request(request)
-
- if err != nil {
- return
- }
-
- if pr.paging.Paging != nil {
- pr.paging.Paging.Next = ""
- pr.paging.Paging.Previous = ""
- }
- paging := &pr.paging
- err = res.Decode(paging)
-
- if err != nil {
- return
- }
-
- if paging.Paging == nil || len(paging.Data) == 0 {
- *url = ""
- noMore = true
- } else {
- pr.previous = paging.Paging.Previous
- pr.next = paging.Paging.Next
- }
-
- return
-}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/params.go b/Godeps/_workspace/src/github.com/huandu/facebook/params.go
deleted file mode 100644
index bcce18a3a..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/params.go
+++ /dev/null
@@ -1,227 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "encoding/json"
- "io"
- "mime/multipart"
- "net/url"
- "os"
- "reflect"
- "runtime"
-)
-
-// Makes a new Params instance by given data.
-// Data must be a struct or a map with string keys.
-// MakeParams will change all struct field name to lower case name with underscore.
-// e.g. "FooBar" will be changed to "foo_bar".
-//
-// Returns nil if data cannot be used to make a Params instance.
-func MakeParams(data interface{}) (params Params) {
- if p, ok := data.(Params); ok {
- return p
- }
-
- defer func() {
- if r := recover(); r != nil {
- if _, ok := r.(runtime.Error); ok {
- panic(r)
- }
-
- params = nil
- }
- }()
-
- params = makeParams(reflect.ValueOf(data))
- return
-}
-
-func makeParams(value reflect.Value) (params Params) {
- for value.Kind() == reflect.Ptr || value.Kind() == reflect.Interface {
- value = value.Elem()
- }
-
- // only map with string keys can be converted to Params
- if value.Kind() == reflect.Map && value.Type().Key().Kind() == reflect.String {
- params = Params{}
-
- for _, key := range value.MapKeys() {
- params[key.String()] = value.MapIndex(key).Interface()
- }
-
- return
- }
-
- if value.Kind() != reflect.Struct {
- return
- }
-
- params = Params{}
- num := value.NumField()
-
- for i := 0; i < num; i++ {
- name := camelCaseToUnderScore(value.Type().Field(i).Name)
- field := value.Field(i)
-
- for field.Kind() == reflect.Ptr {
- field = field.Elem()
- }
-
- switch field.Kind() {
- case reflect.Chan, reflect.Func, reflect.UnsafePointer, reflect.Invalid:
- // these types won't be marshalled in json.
- params = nil
- return
-
- default:
- params[name] = field.Interface()
- }
- }
-
- return
-}
-
-// Encodes params to query string.
-// If map value is not a string, Encode uses json.Marshal() to convert value to string.
-//
-// Encode will panic if Params contains values that cannot be marshalled to json string.
-func (params Params) Encode(writer io.Writer) (mime string, err error) {
- if params == nil || len(params) == 0 {
- mime = _MIME_FORM_URLENCODED
- return
- }
-
- // check whether params contains any binary data.
- hasBinary := false
-
- for _, v := range params {
- typ := reflect.TypeOf(v)
-
- if typ == typeOfPointerToBinaryData || typ == typeOfPointerToBinaryFile {
- hasBinary = true
- break
- }
- }
-
- if hasBinary {
- return params.encodeMultipartForm(writer)
- }
-
- return params.encodeFormUrlEncoded(writer)
-}
-
-func (params Params) encodeFormUrlEncoded(writer io.Writer) (mime string, err error) {
- var jsonStr []byte
- written := false
-
- for k, v := range params {
- if written {
- io.WriteString(writer, "&")
- }
-
- io.WriteString(writer, url.QueryEscape(k))
- io.WriteString(writer, "=")
-
- if reflect.TypeOf(v).Kind() == reflect.String {
- io.WriteString(writer, url.QueryEscape(reflect.ValueOf(v).String()))
- } else {
- jsonStr, err = json.Marshal(v)
-
- if err != nil {
- return
- }
-
- io.WriteString(writer, url.QueryEscape(string(jsonStr)))
- }
-
- written = true
- }
-
- mime = _MIME_FORM_URLENCODED
- return
-}
-
-func (params Params) encodeMultipartForm(writer io.Writer) (mime string, err error) {
- w := multipart.NewWriter(writer)
- defer func() {
- w.Close()
- mime = w.FormDataContentType()
- }()
-
- for k, v := range params {
- switch value := v.(type) {
- case *binaryData:
- var dst io.Writer
- dst, err = w.CreateFormFile(k, value.Filename)
-
- if err != nil {
- return
- }
-
- _, err = io.Copy(dst, value.Source)
-
- if err != nil {
- return
- }
-
- case *binaryFile:
- var dst io.Writer
- var file *os.File
- var path string
-
- dst, err = w.CreateFormFile(k, value.Filename)
-
- if err != nil {
- return
- }
-
- if value.Path == "" {
- path = value.Filename
- } else {
- path = value.Path
- }
-
- file, err = os.Open(path)
-
- if err != nil {
- return
- }
-
- _, err = io.Copy(dst, file)
-
- if err != nil {
- return
- }
-
- default:
- var dst io.Writer
- var jsonStr []byte
-
- dst, err = w.CreateFormField(k)
-
- if reflect.TypeOf(v).Kind() == reflect.String {
- io.WriteString(dst, reflect.ValueOf(v).String())
- } else {
- jsonStr, err = json.Marshal(v)
-
- if err != nil {
- return
- }
-
- _, err = dst.Write(jsonStr)
-
- if err != nil {
- return
- }
- }
- }
- }
-
- return
-}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/result.go b/Godeps/_workspace/src/github.com/huandu/facebook/result.go
deleted file mode 100644
index fd760be4e..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/result.go
+++ /dev/null
@@ -1,1097 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "net/http"
- "reflect"
- "runtime"
- "strconv"
- "strings"
- "time"
-)
-
-// MakeResult makes a Result from facebook Graph API response.
-func MakeResult(jsonBytes []byte) (Result, error) {
- res := Result{}
- err := makeResult(jsonBytes, &res)
-
- if err != nil {
- return nil, err
- }
-
- // facebook may return an error
- return res, res.Err()
-}
-
-func makeResult(jsonBytes []byte, res interface{}) error {
- if bytes.Equal(jsonBytes, facebookSuccessJsonBytes) {
- return nil
- }
-
- jsonReader := bytes.NewReader(jsonBytes)
- dec := json.NewDecoder(jsonReader)
-
- // issue #19
- // app_scoped user_id in a post-Facebook graph 2.0 would exceeds 2^53.
- // use Number instead of float64 to avoid precision lost.
- dec.UseNumber()
-
- err := dec.Decode(res)
-
- if err != nil {
- typ := reflect.TypeOf(res)
-
- if typ != nil {
- // if res is a slice, jsonBytes may be a facebook error.
- // try to decode it as Error.
- kind := typ.Kind()
-
- if kind == reflect.Ptr {
- typ = typ.Elem()
- kind = typ.Kind()
- }
-
- if kind == reflect.Array || kind == reflect.Slice {
- var errRes Result
- err = makeResult(jsonBytes, &errRes)
-
- if err != nil {
- return err
- }
-
- err = errRes.Err()
-
- if err == nil {
- err = fmt.Errorf("cannot format facebook response. expect an array but get an object.")
- }
-
- return err
- }
- }
-
- return fmt.Errorf("cannot format facebook response. %v", err)
- }
-
- return nil
-}
-
-// Get gets a field from Result.
-//
-// Field can be a dot separated string.
-// If field name is "a.b.c", it will try to return value of res["a"]["b"]["c"].
-//
-// To access array items, use index value in field.
-// For instance, field "a.0.c" means to read res["a"][0]["c"].
-//
-// It doesn't work with Result which has a key contains dot. Use GetField in this case.
-//
-// Returns nil if field doesn't exist.
-func (res Result) Get(field string) interface{} {
- if field == "" {
- return res
- }
-
- f := strings.Split(field, ".")
- return res.get(f)
-}
-
-// GetField gets a field from Result.
-//
-// Arguments are treated as keys to access value in Result.
-// If arguments are "a","b","c", it will try to return value of res["a"]["b"]["c"].
-//
-// To access array items, use index value as a string.
-// For instance, args of "a", "0", "c" means to read res["a"][0]["c"].
-//
-// Returns nil if field doesn't exist.
-func (res Result) GetField(fields ...string) interface{} {
- if len(fields) == 0 {
- return res
- }
-
- return res.get(fields)
-}
-
-func (res Result) get(fields []string) interface{} {
- v, ok := res[fields[0]]
-
- if !ok || v == nil {
- return nil
- }
-
- if len(fields) == 1 {
- return v
- }
-
- value := getValueField(reflect.ValueOf(v), fields[1:])
-
- if !value.IsValid() {
- return nil
- }
-
- return value.Interface()
-}
-
-func getValueField(value reflect.Value, fields []string) reflect.Value {
- valueType := value.Type()
- kind := valueType.Kind()
- field := fields[0]
-
- switch kind {
- case reflect.Array, reflect.Slice:
- // field must be a number.
- n, err := strconv.ParseUint(field, 10, 0)
-
- if err != nil {
- return reflect.Value{}
- }
-
- if n >= uint64(value.Len()) {
- return reflect.Value{}
- }
-
- // work around a reflect package pitfall.
- value = reflect.ValueOf(value.Index(int(n)).Interface())
-
- case reflect.Map:
- v := value.MapIndex(reflect.ValueOf(field))
-
- if !v.IsValid() {
- return v
- }
-
- // get real value type.
- value = reflect.ValueOf(v.Interface())
-
- default:
- return reflect.Value{}
- }
-
- if len(fields) == 1 {
- return value
- }
-
- return getValueField(value, fields[1:])
-}
-
-// Decode decodes full result to a struct.
-// It only decodes fields defined in the struct.
-//
-// As all facebook response fields are lower case strings,
-// Decode will convert all camel-case field names to lower case string.
-// e.g. field name "FooBar" will be converted to "foo_bar".
-// The side effect is that if a struct has 2 fields with only capital
-// differences, decoder will map these fields to a same result value.
-//
-// If a field is missing in the result, Decode keeps it unchanged by default.
-//
-// Decode can read struct field tag value to change default behavior.
-//
-// Examples:
-//
-// type Foo struct {
-// // "id" must exist in response. note the leading comma.
-// Id string `facebook:",required"`
-//
-// // use "name" as field name in response.
-// TheName string `facebook:"name"`
-// }
-//
-// To change default behavior, set a struct tag `facebook:",required"` to fields
-// should not be missing.
-//
-// Returns error if v is not a struct or any required v field name absents in res.
-func (res Result) Decode(v interface{}) (err error) {
- defer func() {
- if r := recover(); r != nil {
- if _, ok := r.(runtime.Error); ok {
- panic(r)
- }
-
- err = r.(error)
- }
- }()
-
- err = res.decode(reflect.ValueOf(v), "")
- return
-}
-
-// DecodeField decodes a field of result to any type, including struct.
-// Field name format is defined in Result.Get().
-//
-// More details about decoding struct see Result.Decode().
-func (res Result) DecodeField(field string, v interface{}) error {
- f := res.Get(field)
-
- if f == nil {
- return fmt.Errorf("field '%v' doesn't exist in result.", field)
- }
-
- return decodeField(reflect.ValueOf(f), reflect.ValueOf(v), field)
-}
-
-// Err returns an error if Result is a Graph API error.
-//
-// The returned error can be converted to Error by type assertion.
-// err := res.Err()
-// if err != nil {
-// if e, ok := err.(*Error); ok {
-// // read more details in e.Message, e.Code and e.Type
-// }
-// }
-//
-// For more information about Graph API Errors, see
-// https://developers.facebook.com/docs/reference/api/errors/
-func (res Result) Err() error {
- var err Error
- e := res.DecodeField("error", &err)
-
- // no "error" in result. result is not an error.
- if e != nil {
- return nil
- }
-
- // code may be missing in error.
- // assign a non-zero value to it.
- if err.Code == 0 {
- err.Code = ERROR_CODE_UNKNOWN
- }
-
- return &err
-}
-
-// Paging creates a PagingResult for this Result and
-// returns error if the Result cannot be used for paging.
-//
-// Facebook uses following JSON structure to response paging information.
-// If "data" doesn't present in Result, Paging will return error.
-// {
-// "data": [...],
-// "paging": {
-// "previous": "https://graph.facebook.com/...",
-// "next": "https://graph.facebook.com/..."
-// }
-// }
-func (res Result) Paging(session *Session) (*PagingResult, error) {
- return newPagingResult(session, res)
-}
-
-// Batch creates a BatchResult for this result and
-// returns error if the Result is not a batch api response.
-//
-// See BatchApi document for a sample usage.
-func (res Result) Batch() (*BatchResult, error) {
- return newBatchResult(res)
-}
-
-// DebugInfo creates a DebugInfo for this result if this result
-// has "__debug__" key.
-func (res Result) DebugInfo() *DebugInfo {
- var info Result
- err := res.DecodeField(debugInfoKey, &info)
-
- if err != nil {
- return nil
- }
-
- debugInfo := &DebugInfo{}
- info.DecodeField("messages", &debugInfo.Messages)
-
- if proto, ok := info[debugProtoKey]; ok {
- if v, ok := proto.(string); ok {
- debugInfo.Proto = v
- }
- }
-
- if header, ok := info[debugHeaderKey]; ok {
- if v, ok := header.(http.Header); ok {
- debugInfo.Header = v
-
- debugInfo.FacebookApiVersion = v.Get(facebookApiVersionHeader)
- debugInfo.FacebookDebug = v.Get(facebookDebugHeader)
- debugInfo.FacebookRev = v.Get(facebookRevHeader)
- }
- }
-
- return debugInfo
-}
-
-func (res Result) decode(v reflect.Value, fullName string) error {
- for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
- v = v.Elem()
- }
-
- if v.Kind() != reflect.Struct {
- return fmt.Errorf("output value must be a struct.")
- }
-
- if !v.CanSet() {
- return fmt.Errorf("output value cannot be set.")
- }
-
- if fullName != "" {
- fullName += "."
- }
-
- var field reflect.Value
- var name, fbTag string
- var val interface{}
- var ok, required bool
- var err error
-
- vType := v.Type()
- num := vType.NumField()
-
- for i := 0; i < num; i++ {
- name = ""
- required = false
- field = v.Field(i)
- fbTag = vType.Field(i).Tag.Get("facebook")
-
- // parse struct field tag
- if fbTag != "" {
- index := strings.IndexRune(fbTag, ',')
-
- if index == -1 {
- name = fbTag
- } else {
- name = fbTag[:index]
-
- if fbTag[index:] == ",required" {
- required = true
- }
- }
- }
-
- if name == "" {
- name = camelCaseToUnderScore(v.Type().Field(i).Name)
- }
-
- val, ok = res[name]
-
- if !ok {
- // check whether the field is required. if so, report error.
- if required {
- return fmt.Errorf("cannot find field '%v%v' in result.", fullName, name)
- }
-
- continue
- }
-
- if err = decodeField(reflect.ValueOf(val), field, fmt.Sprintf("%v%v", fullName, name)); err != nil {
- return err
- }
- }
-
- return nil
-}
-
-func decodeField(val reflect.Value, field reflect.Value, fullName string) error {
- if field.Kind() == reflect.Ptr {
- // reset Ptr field if val is nil.
- if !val.IsValid() {
- if !field.IsNil() && field.CanSet() {
- field.Set(reflect.Zero(field.Type()))
- }
-
- return nil
- }
-
- if field.IsNil() {
- field.Set(reflect.New(field.Type().Elem()))
- }
-
- field = field.Elem()
- }
-
- if !field.CanSet() {
- return fmt.Errorf("field '%v' cannot be decoded. make sure the output value is able to be set.", fullName)
- }
-
- if !val.IsValid() {
- return fmt.Errorf("field '%v' is not a pointer. cannot assign nil to it.", fullName)
- }
-
- kind := field.Kind()
- valType := val.Type()
-
- switch kind {
- case reflect.Bool:
- if valType.Kind() == reflect.Bool {
- field.SetBool(val.Bool())
- } else {
- return fmt.Errorf("field '%v' is not a bool in result.", fullName)
- }
-
- case reflect.Int8:
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
-
- if n < -128 || n > 127 {
- return fmt.Errorf("field '%v' value exceeds the range of int8.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
-
- if n > 127 {
- return fmt.Errorf("field '%v' value exceeds the range of int8.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < -128 || n > 127 {
- return fmt.Errorf("field '%v' value exceeds the range of int8.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseInt(val.String(), 10, 8)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid int8.", fullName)
- }
-
- field.SetInt(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Int16:
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
-
- if n < -32768 || n > 32767 {
- return fmt.Errorf("field '%v' value exceeds the range of int16.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
-
- if n > 32767 {
- return fmt.Errorf("field '%v' value exceeds the range of int16.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < -32768 || n > 32767 {
- return fmt.Errorf("field '%v' value exceeds the range of int16.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseInt(val.String(), 10, 16)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid int16.", fullName)
- }
-
- field.SetInt(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Int32:
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
-
- if n < -2147483648 || n > 2147483647 {
- return fmt.Errorf("field '%v' value exceeds the range of int32.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
-
- if n > 2147483647 {
- return fmt.Errorf("field '%v' value exceeds the range of int32.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < -2147483648 || n > 2147483647 {
- return fmt.Errorf("field '%v' value exceeds the range of int32.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseInt(val.String(), 10, 32)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid int32.", fullName)
- }
-
- field.SetInt(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Int64:
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
- field.SetInt(n)
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
-
- if n > 9223372036854775807 {
- return fmt.Errorf("field '%v' value exceeds the range of int64.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < -9223372036854775808 || n > 9223372036854775807 {
- return fmt.Errorf("field '%v' value exceeds the range of int64.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseInt(val.String(), 10, 64)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid int64.", fullName)
- }
-
- field.SetInt(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Int:
- bits := field.Type().Bits()
-
- var min, max int64
-
- if bits == 32 {
- min = -2147483648
- max = 2147483647
- } else if bits == 64 {
- min = -9223372036854775808
- max = 9223372036854775807
- }
-
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
-
- if n < min || n > max {
- return fmt.Errorf("field '%v' value exceeds the range of int.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
-
- if n > uint64(max) {
- return fmt.Errorf("field '%v' value exceeds the range of int.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < float64(min) || n > float64(max) {
- return fmt.Errorf("field '%v' value exceeds the range of int.", fullName)
- }
-
- field.SetInt(int64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseInt(val.String(), 10, bits)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid int%v.", fullName, bits)
- }
-
- field.SetInt(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Uint8:
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
-
- if n < 0 || n > 0xFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint8.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
-
- if n > 0xFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint8.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < 0 || n > 0xFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint8.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseUint(val.String(), 10, 8)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid uint8.", fullName)
- }
-
- field.SetUint(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Uint16:
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
-
- if n < 0 || n > 0xFFFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint16.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
-
- if n > 0xFFFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint16.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < 0 || n > 0xFFFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint16.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseUint(val.String(), 10, 16)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid uint16.", fullName)
- }
-
- field.SetUint(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Uint32:
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
-
- if n < 0 || n > 0xFFFFFFFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint32.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
-
- if n > 0xFFFFFFFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint32.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < 0 || n > 0xFFFFFFFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint32.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseUint(val.String(), 10, 32)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid uint32.", fullName)
- }
-
- field.SetUint(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Uint64:
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
-
- if n < 0 {
- return fmt.Errorf("field '%v' value exceeds the range of uint64.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
- field.SetUint(n)
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < 0 || n > 0xFFFFFFFFFFFFFFFF {
- return fmt.Errorf("field '%v' value exceeds the range of uint64.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseUint(val.String(), 10, 64)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid uint64.", fullName)
- }
-
- field.SetUint(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Uint:
- bits := field.Type().Bits()
-
- var max uint64
-
- if bits == 32 {
- max = 0xFFFFFFFF
- } else if bits == 64 {
- max = 0xFFFFFFFFFFFFFFFF
- }
-
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
-
- if n < 0 || uint64(n) > max {
- return fmt.Errorf("field '%v' value exceeds the range of uint.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
-
- if n > max {
- return fmt.Errorf("field '%v' value exceeds the range of uint.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
-
- if n < 0 || n > float64(max) {
- return fmt.Errorf("field '%v' value exceeds the range of uint.", fullName)
- }
-
- field.SetUint(uint64(n))
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseUint(val.String(), 10, bits)
-
- if err != nil {
- return fmt.Errorf("field '%v' value is not a valid uint%v.", fullName, bits)
- }
-
- field.SetUint(n)
-
- default:
- return fmt.Errorf("field '%v' is not an integer in result.", fullName)
- }
-
- case reflect.Float32, reflect.Float64:
- switch valType.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n := val.Int()
- field.SetFloat(float64(n))
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- n := val.Uint()
- field.SetFloat(float64(n))
-
- case reflect.Float32, reflect.Float64:
- n := val.Float()
- field.SetFloat(n)
-
- case reflect.String:
- // only json.Number is allowed to be used as number.
- if val.Type() != typeOfJSONNumber {
- return fmt.Errorf("field '%v' value is string, not a number.", fullName)
- }
-
- n, err := strconv.ParseFloat(val.String(), 64)
-
- if err != nil {
- return fmt.Errorf("field '%v' is not a valid float64.", fullName)
- }
-
- field.SetFloat(n)
-
- default:
- return fmt.Errorf("field '%v' is not a float in result.", fullName)
- }
-
- case reflect.String:
- if valType.Kind() != reflect.String {
- return fmt.Errorf("field '%v' is not a string in result.", fullName)
- }
-
- field.SetString(val.String())
-
- case reflect.Struct:
- if field.Type().ConvertibleTo(typeOfTime) {
- if valType.Kind() != reflect.String {
- return fmt.Errorf("field '%v' is not a string in result.", fullName)
- }
-
- t, err := time.Parse("2006-01-02T15:04:05-0700", val.String())
-
- if err != nil {
- return fmt.Errorf("field '%v' was unable to parse the time string '%s'.", fullName, val.String())
- }
-
- matchedType := reflect.ValueOf(t).Convert(field.Type())
- field.Set(matchedType)
- return nil
- }
-
- if valType.Kind() != reflect.Map || valType.Key().Kind() != reflect.String {
- return fmt.Errorf("field '%v' is not a json object in result.", fullName)
- }
-
- // safe convert val to Result. type assertion doesn't work in this case.
- var r Result
- reflect.ValueOf(&r).Elem().Set(val)
-
- if err := r.decode(field, fullName); err != nil {
- return err
- }
-
- case reflect.Map:
- if valType.Kind() != reflect.Map || valType.Key().Kind() != reflect.String {
- return fmt.Errorf("field '%v' is not a json object in result.", fullName)
- }
-
- // map key must be string
- if field.Type().Key().Kind() != reflect.String {
- return fmt.Errorf("field '%v' in struct is a map with non-string key type. it's not allowed.", fullName)
- }
-
- var needAddr bool
- valueType := field.Type().Elem()
-
- // shortcut for map[string]interface{}.
- if valueType.Kind() == reflect.Interface {
- field.Set(val)
- break
- }
-
- if field.IsNil() {
- field.Set(reflect.MakeMap(field.Type()))
- }
-
- if valueType.Kind() == reflect.Ptr {
- valueType = valueType.Elem()
- needAddr = true
- }
-
- for _, key := range val.MapKeys() {
- // val.MapIndex(key) returns a Value with wrong type.
- // use following trick to get correct Value.
- value := reflect.ValueOf(val.MapIndex(key).Interface())
- newValue := reflect.New(valueType)
-
- if err := decodeField(value, newValue, fmt.Sprintf("%v.%v", fullName, key)); err != nil {
- return err
- }
-
- if needAddr {
- field.SetMapIndex(key, newValue)
- } else {
- field.SetMapIndex(key, newValue.Elem())
- }
- }
-
- case reflect.Slice, reflect.Array:
- if valType.Kind() != reflect.Slice && valType.Kind() != reflect.Array {
- return fmt.Errorf("field '%v' is not a json array in result.", fullName)
- }
-
- valLen := val.Len()
-
- if kind == reflect.Array {
- if field.Len() < valLen {
- return fmt.Errorf("cannot copy all field '%v' values to struct. expected len is %v. actual len is %v.",
- fullName, field.Len(), valLen)
- }
- }
-
- var slc reflect.Value
- var needAddr bool
-
- valueType := field.Type().Elem()
-
- // shortcut for array of interface
- if valueType.Kind() == reflect.Interface {
- if kind == reflect.Array {
- for i := 0; i < valLen; i++ {
- field.Index(i).Set(val.Index(i))
- }
- } else { // kind is slice
- field.Set(val)
- }
-
- break
- }
-
- if kind == reflect.Array {
- slc = field.Slice(0, valLen)
- } else {
- // kind is slice
- slc = reflect.MakeSlice(field.Type(), valLen, valLen)
- field.Set(slc)
- }
-
- if valueType.Kind() == reflect.Ptr {
- needAddr = true
- valueType = valueType.Elem()
- }
-
- for i := 0; i < valLen; i++ {
- // val.Index(i) returns a Value with wrong type.
- // use following trick to get correct Value.
- valIndexValue := reflect.ValueOf(val.Index(i).Interface())
- newValue := reflect.New(valueType)
-
- if err := decodeField(valIndexValue, newValue, fmt.Sprintf("%v.%v", fullName, i)); err != nil {
- return err
- }
-
- if needAddr {
- slc.Index(i).Set(newValue)
- } else {
- slc.Index(i).Set(newValue.Elem())
- }
- }
-
- default:
- return fmt.Errorf("field '%v' in struct uses unsupported type '%v'.", fullName, kind)
- }
-
- return nil
-}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/session.go b/Godeps/_workspace/src/github.com/huandu/facebook/session.go
deleted file mode 100644
index 95b4ad8d2..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/session.go
+++ /dev/null
@@ -1,667 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "bytes"
- "crypto/hmac"
- "crypto/sha256"
- "encoding/base64"
- "encoding/hex"
- "fmt"
- "io"
- "net/http"
- "net/url"
- "strings"
-)
-
-// Makes a facebook graph api call.
-//
-// If session access token is set, "access_token" in params will be set to the token value.
-//
-// Returns facebook graph api call result.
-// If facebook returns error in response, returns error details in res and set err.
-func (session *Session) Api(path string, method Method, params Params) (Result, error) {
- return session.graph(path, method, params)
-}
-
-// Get is a short hand of Api(path, GET, params).
-func (session *Session) Get(path string, params Params) (Result, error) {
- return session.Api(path, GET, params)
-}
-
-// Post is a short hand of Api(path, POST, params).
-func (session *Session) Post(path string, params Params) (Result, error) {
- return session.Api(path, POST, params)
-}
-
-// Delete is a short hand of Api(path, DELETE, params).
-func (session *Session) Delete(path string, params Params) (Result, error) {
- return session.Api(path, DELETE, params)
-}
-
-// Put is a short hand of Api(path, PUT, params).
-func (session *Session) Put(path string, params Params) (Result, error) {
- return session.Api(path, PUT, params)
-}
-
-// Makes a batch call. Each params represent a single facebook graph api call.
-//
-// BatchApi supports most kinds of batch calls defines in facebook batch api document,
-// except uploading binary data. Use Batch to upload binary data.
-//
-// If session access token is set, the token will be used in batch api call.
-//
-// Returns an array of batch call result on success.
-//
-// Facebook document: https://developers.facebook.com/docs/graph-api/making-multiple-requests
-func (session *Session) BatchApi(params ...Params) ([]Result, error) {
- return session.Batch(nil, params...)
-}
-
-// Makes a batch facebook graph api call.
-// Batch is designed for more advanced usage including uploading binary files.
-//
-// If session access token is set, "access_token" in batchParams will be set to the token value.
-//
-// Facebook document: https://developers.facebook.com/docs/graph-api/making-multiple-requests
-func (session *Session) Batch(batchParams Params, params ...Params) ([]Result, error) {
- return session.graphBatch(batchParams, params...)
-}
-
-// Makes a FQL query.
-// Returns a slice of Result. If there is no query result, the result is nil.
-//
-// Facebook document: https://developers.facebook.com/docs/technical-guides/fql#query
-func (session *Session) FQL(query string) ([]Result, error) {
- res, err := session.graphFQL(Params{
- "q": query,
- })
-
- if err != nil {
- return nil, err
- }
-
- // query result is stored in "data" field.
- var data []Result
- err = res.DecodeField("data", &data)
-
- if err != nil {
- return nil, err
- }
-
- return data, nil
-}
-
-// Makes a multi FQL query.
-// Returns a parsed Result. The key is the multi query key, and the value is the query result.
-//
-// Here is a multi-query sample.
-//
-// res, _ := session.MultiFQL(Params{
-// "query1": "SELECT name FROM user WHERE uid = me()",
-// "query2": "SELECT uid1, uid2 FROM friend WHERE uid1 = me()",
-// })
-//
-// // Get query results from response.
-// var query1, query2 []Result
-// res.DecodeField("query1", &query1)
-// res.DecodeField("query2", &query2)
-//
-// Facebook document: https://developers.facebook.com/docs/technical-guides/fql#multi
-func (session *Session) MultiFQL(queries Params) (Result, error) {
- res, err := session.graphFQL(Params{
- "q": queries,
- })
-
- if err != nil {
- return res, err
- }
-
- // query result is stored in "data" field.
- var data []Result
- err = res.DecodeField("data", &data)
-
- if err != nil {
- return nil, err
- }
-
- if data == nil {
- return nil, fmt.Errorf("multi-fql result is not found.")
- }
-
- // Multi-fql data structure is:
- // {
- // "data": [
- // {
- // "name": "query1",
- // "fql_result_set": [
- // {...}, {...}, ...
- // ]
- // },
- // {
- // "name": "query2",
- // "fql_result_set": [
- // {...}, {...}, ...
- // ]
- // },
- // ...
- // ]
- // }
- //
- // Parse the structure to following go map.
- // {
- // "query1": [
- // // Come from field "fql_result_set".
- // {...}, {...}, ...
- // ],
- // "query2": [
- // {...}, {...}, ...
- // ],
- // ...
- // }
- var name string
- var apiResponse interface{}
- var ok bool
- result := Result{}
-
- for k, v := range data {
- err = v.DecodeField("name", &name)
-
- if err != nil {
- return nil, fmt.Errorf("missing required field 'name' in multi-query data.%v. %v", k, err)
- }
-
- apiResponse, ok = v["fql_result_set"]
-
- if !ok {
- return nil, fmt.Errorf("missing required field 'fql_result_set' in multi-query data.%v.", k)
- }
-
- result[name] = apiResponse
- }
-
- return result, nil
-}
-
-// Makes an arbitrary HTTP request.
-// It expects server responses a facebook Graph API response.
-// request, _ := http.NewRequest("https://graph.facebook.com/538744468", "GET", nil)
-// res, err := session.Request(request)
-// fmt.Println(res["gender"]) // get "male"
-func (session *Session) Request(request *http.Request) (res Result, err error) {
- var response *http.Response
- var data []byte
-
- response, data, err = session.sendRequest(request)
-
- if err != nil {
- return
- }
-
- res, err = MakeResult(data)
- session.addDebugInfo(res, response)
-
- if res != nil {
- err = res.Err()
- }
-
- return
-}
-
-// Gets current user id from access token.
-//
-// Returns error if access token is not set or invalid.
-//
-// It's a standard way to validate a facebook access token.
-func (session *Session) User() (id string, err error) {
- if session.id != "" {
- id = session.id
- return
- }
-
- if session.accessToken == "" {
- err = fmt.Errorf("access token is not set.")
- return
- }
-
- var result Result
- result, err = session.Api("/me", GET, Params{"fields": "id"})
-
- if err != nil {
- return
- }
-
- err = result.DecodeField("id", &id)
-
- if err != nil {
- return
- }
-
- return
-}
-
-// Validates Session access token.
-// Returns nil if access token is valid.
-func (session *Session) Validate() (err error) {
- if session.accessToken == "" {
- err = fmt.Errorf("access token is not set.")
- return
- }
-
- var result Result
- result, err = session.Api("/me", GET, Params{"fields": "id"})
-
- if err != nil {
- return
- }
-
- if f := result.Get("id"); f == nil {
- err = fmt.Errorf("invalid access token.")
- return
- }
-
- return
-}
-
-// Inspect Session access token.
-// Returns JSON array containing data about the inspected token.
-// See https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2#checktoken
-func (session *Session) Inspect() (result Result, err error) {
- if session.accessToken == "" {
- err = fmt.Errorf("access token is not set.")
- return
- }
-
- if session.app == nil {
- err = fmt.Errorf("cannot inspect access token without binding an app.")
- return
- }
-
- appAccessToken := session.app.AppAccessToken()
-
- if appAccessToken == "" {
- err = fmt.Errorf("app access token is not set.")
- return
- }
-
- result, err = session.Api("/debug_token", GET, Params{
- "input_token": session.accessToken,
- "access_token": appAccessToken,
- })
-
- if err != nil {
- return
- }
-
- // facebook stores everything, including error, inside result["data"].
- // make sure that result["data"] exists and doesn't contain error.
- if _, ok := result["data"]; !ok {
- err = fmt.Errorf("facebook inspect api returns unexpected result.")
- return
- }
-
- var data Result
- result.DecodeField("data", &data)
- result = data
- err = result.Err()
- return
-}
-
-// Gets current access token.
-func (session *Session) AccessToken() string {
- return session.accessToken
-}
-
-// Sets a new access token.
-func (session *Session) SetAccessToken(token string) {
- if token != session.accessToken {
- session.id = ""
- session.accessToken = token
- session.appsecretProof = ""
- }
-}
-
-// Check appsecret proof is enabled or not.
-func (session *Session) AppsecretProof() string {
- if !session.enableAppsecretProof {
- return ""
- }
-
- if session.accessToken == "" || session.app == nil {
- return ""
- }
-
- if session.appsecretProof == "" {
- hash := hmac.New(sha256.New, []byte(session.app.AppSecret))
- hash.Write([]byte(session.accessToken))
- session.appsecretProof = hex.EncodeToString(hash.Sum(nil))
- }
-
- return session.appsecretProof
-}
-
-// Enable or disable appsecret proof status.
-// Returns error if there is no App associasted with this Session.
-func (session *Session) EnableAppsecretProof(enabled bool) error {
- if session.app == nil {
- return fmt.Errorf("cannot change appsecret proof status without an associated App.")
- }
-
- if session.enableAppsecretProof != enabled {
- session.enableAppsecretProof = enabled
-
- // reset pre-calculated proof here to give caller a way to do so in some rare case,
- // e.g. associated app's secret is changed.
- session.appsecretProof = ""
- }
-
- return nil
-}
-
-// Gets associated App.
-func (session *Session) App() *App {
- return session.app
-}
-
-// Debug returns current debug mode.
-func (session *Session) Debug() DebugMode {
- if session.debug != DEBUG_OFF {
- return session.debug
- }
-
- return Debug
-}
-
-// SetDebug updates per session debug mode and returns old mode.
-// If per session debug mode is DEBUG_OFF, session will use global
-// Debug mode.
-func (session *Session) SetDebug(debug DebugMode) DebugMode {
- old := session.debug
- session.debug = debug
- return old
-}
-
-func (session *Session) graph(path string, method Method, params Params) (res Result, err error) {
- var graphUrl string
-
- if params == nil {
- params = Params{}
- }
-
- // always format as json.
- params["format"] = "json"
-
- // overwrite method as we always use post
- params["method"] = method
-
- // get graph api url.
- if session.isVideoPost(path, method) {
- graphUrl = session.getUrl("graph_video", path, nil)
- } else {
- graphUrl = session.getUrl("graph", path, nil)
- }
-
- var response *http.Response
- response, err = session.sendPostRequest(graphUrl, params, &res)
- session.addDebugInfo(res, response)
-
- if res != nil {
- err = res.Err()
- }
-
- return
-}
-
-func (session *Session) graphBatch(batchParams Params, params ...Params) ([]Result, error) {
- if batchParams == nil {
- batchParams = Params{}
- }
-
- batchParams["batch"] = params
-
- var res []Result
- graphUrl := session.getUrl("graph", "", nil)
- _, err := session.sendPostRequest(graphUrl, batchParams, &res)
- return res, err
-}
-
-func (session *Session) graphFQL(params Params) (res Result, err error) {
- if params == nil {
- params = Params{}
- }
-
- session.prepareParams(params)
-
- // encode url.
- buf := &bytes.Buffer{}
- buf.WriteString(domainMap["graph"])
- buf.WriteString("fql?")
- _, err = params.Encode(buf)
-
- if err != nil {
- return nil, fmt.Errorf("cannot encode params. %v", err)
- }
-
- // it seems facebook disallow POST to /fql. always use GET for FQL.
- var response *http.Response
- response, err = session.sendGetRequest(buf.String(), &res)
- session.addDebugInfo(res, response)
-
- if res != nil {
- err = res.Err()
- }
-
- return
-}
-
-func (session *Session) prepareParams(params Params) {
- if _, ok := params["access_token"]; !ok && session.accessToken != "" {
- params["access_token"] = session.accessToken
- }
-
- if session.enableAppsecretProof && session.accessToken != "" && session.app != nil {
- params["appsecret_proof"] = session.AppsecretProof()
- }
-
- debug := session.Debug()
-
- if debug != DEBUG_OFF {
- params["debug"] = debug
- }
-}
-
-func (session *Session) sendGetRequest(uri string, res interface{}) (*http.Response, error) {
- request, err := http.NewRequest("GET", uri, nil)
-
- if err != nil {
- return nil, err
- }
-
- response, data, err := session.sendRequest(request)
-
- if err != nil {
- return response, err
- }
-
- err = makeResult(data, res)
- return response, err
-}
-
-func (session *Session) sendPostRequest(uri string, params Params, res interface{}) (*http.Response, error) {
- session.prepareParams(params)
-
- buf := &bytes.Buffer{}
- mime, err := params.Encode(buf)
-
- if err != nil {
- return nil, fmt.Errorf("cannot encode POST params. %v", err)
- }
-
- var request *http.Request
-
- request, err = http.NewRequest("POST", uri, buf)
-
- if err != nil {
- return nil, err
- }
-
- request.Header.Set("Content-Type", mime)
- response, data, err := session.sendRequest(request)
-
- if err != nil {
- return response, err
- }
-
- err = makeResult(data, res)
- return response, err
-}
-
-func (session *Session) sendOauthRequest(uri string, params Params) (Result, error) {
- urlStr := session.getUrl("graph", uri, nil)
- buf := &bytes.Buffer{}
- mime, err := params.Encode(buf)
-
- if err != nil {
- return nil, fmt.Errorf("cannot encode POST params. %v", err)
- }
-
- var request *http.Request
-
- request, err = http.NewRequest("POST", urlStr, buf)
-
- if err != nil {
- return nil, err
- }
-
- request.Header.Set("Content-Type", mime)
- _, data, err := session.sendRequest(request)
-
- if err != nil {
- return nil, err
- }
-
- if len(data) == 0 {
- return nil, fmt.Errorf("empty response from facebook")
- }
-
- // facebook may return a query string.
- if 'a' <= data[0] && data[0] <= 'z' {
- query, err := url.ParseQuery(string(data))
-
- if err != nil {
- return nil, err
- }
-
- // convert a query to Result.
- res := Result{}
-
- for k := range query {
- res[k] = query.Get(k)
- }
-
- return res, nil
- }
-
- res, err := MakeResult(data)
- return res, err
-}
-
-func (session *Session) sendRequest(request *http.Request) (response *http.Response, data []byte, err error) {
- if session.HttpClient == nil {
- response, err = http.DefaultClient.Do(request)
- } else {
- response, err = session.HttpClient.Do(request)
- }
-
- if err != nil {
- err = fmt.Errorf("cannot reach facebook server. %v", err)
- return
- }
-
- buf := &bytes.Buffer{}
- _, err = io.Copy(buf, response.Body)
- response.Body.Close()
-
- if err != nil {
- err = fmt.Errorf("cannot read facebook response. %v", err)
- }
-
- data = buf.Bytes()
- return
-}
-
-func (session *Session) isVideoPost(path string, method Method) bool {
- return method == POST && regexpIsVideoPost.MatchString(path)
-}
-
-func (session *Session) getUrl(name, path string, params Params) string {
- offset := 0
-
- if path != "" && path[0] == '/' {
- offset = 1
- }
-
- buf := &bytes.Buffer{}
- buf.WriteString(domainMap[name])
-
- // facebook versioning.
- if session.Version == "" {
- if Version != "" {
- buf.WriteString(Version)
- buf.WriteRune('/')
- }
- } else {
- buf.WriteString(session.Version)
- buf.WriteRune('/')
- }
-
- buf.WriteString(string(path[offset:]))
-
- if params != nil {
- buf.WriteRune('?')
- params.Encode(buf)
- }
-
- return buf.String()
-}
-
-func (session *Session) addDebugInfo(res Result, response *http.Response) Result {
- if session.Debug() == DEBUG_OFF || res == nil || response == nil {
- return res
- }
-
- debugInfo := make(map[string]interface{})
-
- // save debug information in result directly.
- res.DecodeField("__debug__", &debugInfo)
- debugInfo[debugProtoKey] = response.Proto
- debugInfo[debugHeaderKey] = response.Header
-
- res["__debug__"] = debugInfo
- return res
-}
-
-func decodeBase64URLEncodingString(data string) ([]byte, error) {
- buf := bytes.NewBufferString(data)
-
- // go's URLEncoding implementation requires base64 padding.
- if m := len(data) % 4; m != 0 {
- buf.WriteString(strings.Repeat("=", 4-m))
- }
-
- reader := base64.NewDecoder(base64.URLEncoding, buf)
- output := &bytes.Buffer{}
- _, err := io.Copy(output, reader)
-
- if err != nil {
- return nil, err
- }
-
- return output.Bytes(), nil
-}
diff --git a/Godeps/_workspace/src/github.com/huandu/facebook/type.go b/Godeps/_workspace/src/github.com/huandu/facebook/type.go
deleted file mode 100644
index d09865415..000000000
--- a/Godeps/_workspace/src/github.com/huandu/facebook/type.go
+++ /dev/null
@@ -1,127 +0,0 @@
-// A facebook graph api client in go.
-// https://github.com/huandu/facebook/
-//
-// Copyright 2012 - 2015, Huan Du
-// Licensed under the MIT license
-// https://github.com/huandu/facebook/blob/master/LICENSE
-
-package facebook
-
-import (
- "io"
- "net/http"
-)
-
-// Holds facebook application information.
-type App struct {
- // Facebook app id
- AppId string
-
- // Facebook app secret
- AppSecret string
-
- // Facebook app redirect URI in the app's configuration.
- RedirectUri string
-
- // Enable appsecret proof in every API call to facebook.
- // Facebook document: https://developers.facebook.com/docs/graph-api/securing-requests
- EnableAppsecretProof bool
-}
-
-// An interface to send http request.
-// This interface is designed to be compatible with type `*http.Client`.
-type HttpClient interface {
- Do(req *http.Request) (resp *http.Response, err error)
- Get(url string) (resp *http.Response, err error)
- Post(url string, bodyType string, body io.Reader) (resp *http.Response, err error)
-}
-
-// Holds a facebook session with an access token.
-// Session should be created by App.Session or App.SessionFromSignedRequest.
-type Session struct {
- HttpClient HttpClient
- Version string // facebook versioning.
-
- accessToken string // facebook access token. can be empty.
- app *App
- id string
-
- enableAppsecretProof bool // add "appsecret_proof" parameter in every facebook API call.
- appsecretProof string // pre-calculated "appsecret_proof" value.
-
- debug DebugMode // using facebook debugging api in every request.
-}
-
-// API HTTP method.
-// Can be GET, POST or DELETE.
-type Method string
-
-// Graph API debug mode.
-// See https://developers.facebook.com/docs/graph-api/using-graph-api/v2.3#graphapidebugmode
-type DebugMode string
-
-// API params.
-//
-// For general uses, just use Params as a ordinary map.
-//
-// For advanced uses, use MakeParams to create Params from any struct.
-type Params map[string]interface{}
-
-// Facebook API call result.
-type Result map[string]interface{}
-
-// Represents facebook API call result with paging information.
-type PagingResult struct {
- session *Session
- paging pagingData
- previous string
- next string
-}
-
-// Represents facebook batch API call result.
-// See https://developers.facebook.com/docs/graph-api/making-multiple-requests/#multiple_methods.
-type BatchResult struct {
- StatusCode int // HTTP status code.
- Header http.Header // HTTP response headers.
- Body string // Raw HTTP response body string.
- Result Result // Facebook api result parsed from body.
-}
-
-// Facebook API error.
-type Error struct {
- Message string
- Type string
- Code int
- ErrorSubcode int // subcode for authentication related errors.
-}
-
-// Binary data.
-type binaryData struct {
- Filename string // filename used in multipart form writer.
- Source io.Reader // file data source.
-}
-
-// Binary file.
-type binaryFile struct {
- Filename string // filename used in multipart form writer.
- Path string // path to file. must be readable.
-}
-
-// DebugInfo is the debug information returned by facebook when debug mode is enabled.
-type DebugInfo struct {
- Messages []DebugMessage // debug messages. it can be nil if there is no message.
- Header http.Header // all HTTP headers for this response.
- Proto string // HTTP protocol name for this response.
-
- // Facebook debug HTTP headers.
- FacebookApiVersion string // the actual graph API version provided by facebook-api-version HTTP header.
- FacebookDebug string // the X-FB-Debug HTTP header.
- FacebookRev string // the x-fb-rev HTTP header.
-}
-
-// DebugMessage is one debug message in "__debug__" of graph API response.
-type DebugMessage struct {
- Type string
- Message string
- Link string
-}
diff --git a/Godeps/_workspace/src/golang.org/x/image/bmp/reader.go b/Godeps/_workspace/src/golang.org/x/image/bmp/reader.go
new file mode 100644
index 000000000..a48cba84d
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/image/bmp/reader.go
@@ -0,0 +1,199 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package bmp implements a BMP image decoder and encoder.
+//
+// The BMP specification is at http://www.digicamsoft.com/bmp/bmp.html.
+package bmp
+
+import (
+ "errors"
+ "image"
+ "image/color"
+ "io"
+)
+
+// ErrUnsupported means that the input BMP image uses a valid but unsupported
+// feature.
+var ErrUnsupported = errors.New("bmp: unsupported BMP image")
+
+func readUint16(b []byte) uint16 {
+ return uint16(b[0]) | uint16(b[1])<<8
+}
+
+func readUint32(b []byte) uint32 {
+ return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+}
+
+// decodePaletted reads an 8 bit-per-pixel BMP image from r.
+// If topDown is false, the image rows will be read bottom-up.
+func decodePaletted(r io.Reader, c image.Config, topDown bool) (image.Image, error) {
+ paletted := image.NewPaletted(image.Rect(0, 0, c.Width, c.Height), c.ColorModel.(color.Palette))
+ if c.Width == 0 || c.Height == 0 {
+ return paletted, nil
+ }
+ var tmp [4]byte
+ y0, y1, yDelta := c.Height-1, -1, -1
+ if topDown {
+ y0, y1, yDelta = 0, c.Height, +1
+ }
+ for y := y0; y != y1; y += yDelta {
+ p := paletted.Pix[y*paletted.Stride : y*paletted.Stride+c.Width]
+ if _, err := io.ReadFull(r, p); err != nil {
+ return nil, err
+ }
+ // Each row is 4-byte aligned.
+ if c.Width%4 != 0 {
+ _, err := io.ReadFull(r, tmp[:4-c.Width%4])
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+ return paletted, nil
+}
+
+// decodeRGB reads a 24 bit-per-pixel BMP image from r.
+// If topDown is false, the image rows will be read bottom-up.
+func decodeRGB(r io.Reader, c image.Config, topDown bool) (image.Image, error) {
+ rgba := image.NewRGBA(image.Rect(0, 0, c.Width, c.Height))
+ if c.Width == 0 || c.Height == 0 {
+ return rgba, nil
+ }
+ // There are 3 bytes per pixel, and each row is 4-byte aligned.
+ b := make([]byte, (3*c.Width+3)&^3)
+ y0, y1, yDelta := c.Height-1, -1, -1
+ if topDown {
+ y0, y1, yDelta = 0, c.Height, +1
+ }
+ for y := y0; y != y1; y += yDelta {
+ if _, err := io.ReadFull(r, b); err != nil {
+ return nil, err
+ }
+ p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4]
+ for i, j := 0, 0; i < len(p); i, j = i+4, j+3 {
+ // BMP images are stored in BGR order rather than RGB order.
+ p[i+0] = b[j+2]
+ p[i+1] = b[j+1]
+ p[i+2] = b[j+0]
+ p[i+3] = 0xFF
+ }
+ }
+ return rgba, nil
+}
+
+// decodeNRGBA reads a 32 bit-per-pixel BMP image from r.
+// If topDown is false, the image rows will be read bottom-up.
+func decodeNRGBA(r io.Reader, c image.Config, topDown bool) (image.Image, error) {
+ rgba := image.NewNRGBA(image.Rect(0, 0, c.Width, c.Height))
+ if c.Width == 0 || c.Height == 0 {
+ return rgba, nil
+ }
+ y0, y1, yDelta := c.Height-1, -1, -1
+ if topDown {
+ y0, y1, yDelta = 0, c.Height, +1
+ }
+ for y := y0; y != y1; y += yDelta {
+ p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4]
+ if _, err := io.ReadFull(r, p); err != nil {
+ return nil, err
+ }
+ for i := 0; i < len(p); i += 4 {
+ // BMP images are stored in BGRA order rather than RGBA order.
+ p[i+0], p[i+2] = p[i+2], p[i+0]
+ }
+ }
+ return rgba, nil
+}
+
+// Decode reads a BMP image from r and returns it as an image.Image.
+// Limitation: The file must be 8, 24 or 32 bits per pixel.
+func Decode(r io.Reader) (image.Image, error) {
+ c, bpp, topDown, err := decodeConfig(r)
+ if err != nil {
+ return nil, err
+ }
+ switch bpp {
+ case 8:
+ return decodePaletted(r, c, topDown)
+ case 24:
+ return decodeRGB(r, c, topDown)
+ case 32:
+ return decodeNRGBA(r, c, topDown)
+ }
+ panic("unreachable")
+}
+
+// DecodeConfig returns the color model and dimensions of a BMP image without
+// decoding the entire image.
+// Limitation: The file must be 8, 24 or 32 bits per pixel.
+func DecodeConfig(r io.Reader) (image.Config, error) {
+ config, _, _, err := decodeConfig(r)
+ return config, err
+}
+
+func decodeConfig(r io.Reader) (config image.Config, bitsPerPixel int, topDown bool, err error) {
+ // We only support those BMP images that are a BITMAPFILEHEADER
+ // immediately followed by a BITMAPINFOHEADER.
+ const (
+ fileHeaderLen = 14
+ infoHeaderLen = 40
+ )
+ var b [1024]byte
+ if _, err := io.ReadFull(r, b[:fileHeaderLen+infoHeaderLen]); err != nil {
+ return image.Config{}, 0, false, err
+ }
+ if string(b[:2]) != "BM" {
+ return image.Config{}, 0, false, errors.New("bmp: invalid format")
+ }
+ offset := readUint32(b[10:14])
+ if readUint32(b[14:18]) != infoHeaderLen {
+ return image.Config{}, 0, false, ErrUnsupported
+ }
+ width := int(int32(readUint32(b[18:22])))
+ height := int(int32(readUint32(b[22:26])))
+ if height < 0 {
+ height, topDown = -height, true
+ }
+ if width < 0 || height < 0 {
+ return image.Config{}, 0, false, ErrUnsupported
+ }
+ // We only support 1 plane, 8 or 24 bits per pixel and no compression.
+ planes, bpp, compression := readUint16(b[26:28]), readUint16(b[28:30]), readUint32(b[30:34])
+ if planes != 1 || compression != 0 {
+ return image.Config{}, 0, false, ErrUnsupported
+ }
+ switch bpp {
+ case 8:
+ if offset != fileHeaderLen+infoHeaderLen+256*4 {
+ return image.Config{}, 0, false, ErrUnsupported
+ }
+ _, err = io.ReadFull(r, b[:256*4])
+ if err != nil {
+ return image.Config{}, 0, false, err
+ }
+ pcm := make(color.Palette, 256)
+ for i := range pcm {
+ // BMP images are stored in BGR order rather than RGB order.
+ // Every 4th byte is padding.
+ pcm[i] = color.RGBA{b[4*i+2], b[4*i+1], b[4*i+0], 0xFF}
+ }
+ return image.Config{ColorModel: pcm, Width: width, Height: height}, 8, topDown, nil
+ case 24:
+ if offset != fileHeaderLen+infoHeaderLen {
+ return image.Config{}, 0, false, ErrUnsupported
+ }
+ return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 24, topDown, nil
+ case 32:
+ if offset != fileHeaderLen+infoHeaderLen {
+ return image.Config{}, 0, false, ErrUnsupported
+ }
+ return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 32, topDown, nil
+ }
+ return image.Config{}, 0, false, ErrUnsupported
+}
+
+func init() {
+ image.RegisterFormat("bmp", "BM????\x00\x00\x00\x00", Decode, DecodeConfig)
+}
diff --git a/Godeps/_workspace/src/golang.org/x/image/bmp/reader_test.go b/Godeps/_workspace/src/golang.org/x/image/bmp/reader_test.go
new file mode 100644
index 000000000..fd6ff64f6
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/image/bmp/reader_test.go
@@ -0,0 +1,75 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bmp
+
+import (
+ "fmt"
+ "image"
+ "os"
+ "testing"
+
+ _ "image/png"
+)
+
+const testdataDir = "../testdata/"
+
+func compare(t *testing.T, img0, img1 image.Image) error {
+ b := img1.Bounds()
+ if !b.Eq(img0.Bounds()) {
+ return fmt.Errorf("wrong image size: want %s, got %s", img0.Bounds(), b)
+ }
+ for y := b.Min.Y; y < b.Max.Y; y++ {
+ for x := b.Min.X; x < b.Max.X; x++ {
+ c0 := img0.At(x, y)
+ c1 := img1.At(x, y)
+ r0, g0, b0, a0 := c0.RGBA()
+ r1, g1, b1, a1 := c1.RGBA()
+ if r0 != r1 || g0 != g1 || b0 != b1 || a0 != a1 {
+ return fmt.Errorf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, c0, c1)
+ }
+ }
+ }
+ return nil
+}
+
+// TestDecode tests that decoding a PNG image and a BMP image result in the
+// same pixel data.
+func TestDecode(t *testing.T) {
+ testCases := []string{
+ "video-001",
+ "yellow_rose-small",
+ }
+
+ for _, tc := range testCases {
+ f0, err := os.Open(testdataDir + tc + ".png")
+ if err != nil {
+ t.Errorf("%s: Open PNG: %v", tc, err)
+ continue
+ }
+ defer f0.Close()
+ img0, _, err := image.Decode(f0)
+ if err != nil {
+ t.Errorf("%s: Decode PNG: %v", tc, err)
+ continue
+ }
+
+ f1, err := os.Open(testdataDir + tc + ".bmp")
+ if err != nil {
+ t.Errorf("%s: Open BMP: %v", tc, err)
+ continue
+ }
+ defer f1.Close()
+ img1, _, err := image.Decode(f1)
+ if err != nil {
+ t.Errorf("%s: Decode BMP: %v", tc, err)
+ continue
+ }
+
+ if err := compare(t, img0, img1); err != nil {
+ t.Errorf("%s: %v", tc, err)
+ continue
+ }
+ }
+}
diff --git a/Godeps/_workspace/src/golang.org/x/image/bmp/writer.go b/Godeps/_workspace/src/golang.org/x/image/bmp/writer.go
new file mode 100644
index 000000000..6947968a4
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/image/bmp/writer.go
@@ -0,0 +1,166 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bmp
+
+import (
+ "encoding/binary"
+ "errors"
+ "image"
+ "io"
+)
+
+type header struct {
+ sigBM [2]byte
+ fileSize uint32
+ resverved [2]uint16
+ pixOffset uint32
+ dibHeaderSize uint32
+ width uint32
+ height uint32
+ colorPlane uint16
+ bpp uint16
+ compression uint32
+ imageSize uint32
+ xPixelsPerMeter uint32
+ yPixelsPerMeter uint32
+ colorUse uint32
+ colorImportant uint32
+}
+
+func encodePaletted(w io.Writer, pix []uint8, dx, dy, stride, step int) error {
+ var padding []byte
+ if dx < step {
+ padding = make([]byte, step-dx)
+ }
+ for y := dy - 1; y >= 0; y-- {
+ min := y*stride + 0
+ max := y*stride + dx
+ if _, err := w.Write(pix[min:max]); err != nil {
+ return err
+ }
+ if padding != nil {
+ if _, err := w.Write(padding); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int) error {
+ buf := make([]byte, step)
+ for y := dy - 1; y >= 0; y-- {
+ min := y*stride + 0
+ max := y*stride + dx*4
+ off := 0
+ for i := min; i < max; i += 4 {
+ buf[off+2] = pix[i+0]
+ buf[off+1] = pix[i+1]
+ buf[off+0] = pix[i+2]
+ off += 3
+ }
+ if _, err := w.Write(buf); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func encode(w io.Writer, m image.Image, step int) error {
+ b := m.Bounds()
+ buf := make([]byte, step)
+ for y := b.Max.Y - 1; y >= b.Min.Y; y-- {
+ off := 0
+ for x := b.Min.X; x < b.Max.X; x++ {
+ r, g, b, _ := m.At(x, y).RGBA()
+ buf[off+2] = byte(r >> 8)
+ buf[off+1] = byte(g >> 8)
+ buf[off+0] = byte(b >> 8)
+ off += 3
+ }
+ if _, err := w.Write(buf); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// Encode writes the image m to w in BMP format.
+func Encode(w io.Writer, m image.Image) error {
+ d := m.Bounds().Size()
+ if d.X < 0 || d.Y < 0 {
+ return errors.New("bmp: negative bounds")
+ }
+ h := &header{
+ sigBM: [2]byte{'B', 'M'},
+ fileSize: 14 + 40,
+ pixOffset: 14 + 40,
+ dibHeaderSize: 40,
+ width: uint32(d.X),
+ height: uint32(d.Y),
+ colorPlane: 1,
+ }
+
+ var step int
+ var palette []byte
+ switch m := m.(type) {
+ case *image.Gray:
+ step = (d.X + 3) &^ 3
+ palette = make([]byte, 1024)
+ for i := 0; i < 256; i++ {
+ palette[i*4+0] = uint8(i)
+ palette[i*4+1] = uint8(i)
+ palette[i*4+2] = uint8(i)
+ palette[i*4+3] = 0xFF
+ }
+ h.imageSize = uint32(d.Y * step)
+ h.fileSize += uint32(len(palette)) + h.imageSize
+ h.pixOffset += uint32(len(palette))
+ h.bpp = 8
+
+ case *image.Paletted:
+ step = (d.X + 3) &^ 3
+ palette = make([]byte, 1024)
+ for i := 0; i < len(m.Palette) && i < 256; i++ {
+ r, g, b, _ := m.Palette[i].RGBA()
+ palette[i*4+0] = uint8(b >> 8)
+ palette[i*4+1] = uint8(g >> 8)
+ palette[i*4+2] = uint8(r >> 8)
+ palette[i*4+3] = 0xFF
+ }
+ h.imageSize = uint32(d.Y * step)
+ h.fileSize += uint32(len(palette)) + h.imageSize
+ h.pixOffset += uint32(len(palette))
+ h.bpp = 8
+ default:
+ step = (3*d.X + 3) &^ 3
+ h.imageSize = uint32(d.Y * step)
+ h.fileSize += h.imageSize
+ h.bpp = 24
+ }
+
+ if err := binary.Write(w, binary.LittleEndian, h); err != nil {
+ return err
+ }
+ if palette != nil {
+ if err := binary.Write(w, binary.LittleEndian, palette); err != nil {
+ return err
+ }
+ }
+
+ if d.X == 0 || d.Y == 0 {
+ return nil
+ }
+
+ switch m := m.(type) {
+ case *image.Gray:
+ return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step)
+ case *image.Paletted:
+ return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step)
+ case *image.RGBA:
+ return encodeRGBA(w, m.Pix, d.X, d.Y, m.Stride, step)
+ }
+ return encode(w, m, step)
+}
diff --git a/Godeps/_workspace/src/golang.org/x/image/bmp/writer_test.go b/Godeps/_workspace/src/golang.org/x/image/bmp/writer_test.go
new file mode 100644
index 000000000..9e5a32741
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/image/bmp/writer_test.go
@@ -0,0 +1,91 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bmp
+
+import (
+ "bytes"
+ "fmt"
+ "image"
+ "io/ioutil"
+ "os"
+ "testing"
+ "time"
+)
+
+func openImage(filename string) (image.Image, error) {
+ f, err := os.Open(testdataDir + filename)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ return Decode(f)
+}
+
+func TestEncode(t *testing.T) {
+ img0, err := openImage("video-001.bmp")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ buf := new(bytes.Buffer)
+ err = Encode(buf, img0)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ img1, err := Decode(buf)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ compare(t, img0, img1)
+}
+
+// TestZeroWidthVeryLargeHeight tests that encoding and decoding a degenerate
+// image with zero width but over one billion pixels in height is faster than
+// naively calling an io.Reader or io.Writer method once per row.
+func TestZeroWidthVeryLargeHeight(t *testing.T) {
+ c := make(chan error, 1)
+ go func() {
+ b := image.Rect(0, 0, 0, 0x3fffffff)
+ var buf bytes.Buffer
+ if err := Encode(&buf, image.NewRGBA(b)); err != nil {
+ c <- err
+ return
+ }
+ m, err := Decode(&buf)
+ if err != nil {
+ c <- err
+ return
+ }
+ if got := m.Bounds(); got != b {
+ c <- fmt.Errorf("bounds: got %v, want %v", got, b)
+ return
+ }
+ c <- nil
+ }()
+ select {
+ case err := <-c:
+ if err != nil {
+ t.Fatal(err)
+ }
+ case <-time.After(3 * time.Second):
+ t.Fatalf("timed out")
+ }
+}
+
+// BenchmarkEncode benchmarks the encoding of an image.
+func BenchmarkEncode(b *testing.B) {
+ img, err := openImage("video-001.bmp")
+ if err != nil {
+ b.Fatal(err)
+ }
+ s := img.Bounds().Size()
+ b.SetBytes(int64(s.X * s.Y * 4))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Encode(ioutil.Discard, img)
+ }
+}
diff --git a/Makefile b/Makefile
index dc6cc3dc7..dacc1a19b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-.PHONY: all test clean build install run stop cover dist dist-battlehouse cleandb
+.PHONY: all test clean build install run stop cover dist cleandb travis
GOPATH ?= $(GOPATH:)
GOFLAGS ?= $(GOFLAGS:)
@@ -15,7 +15,25 @@ DIST_RESULTS=$(DIST_ROOT)/results
BENCH=.
TESTS=.
-all: build
+all: travis
+
+travis:
+ @echo building for travis
+
+ rm -Rf $(DIST_ROOT)
+ @go clean $(GOFLAGS) -i ./...
+
+ @cd web/react/ && npm install
+
+ @go build $(GOFLAGS) ./...
+
+ @mkdir -p logs
+
+ @go test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=180s ./api || exit 1
+ @go test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=12s ./model || exit 1
+ @go test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./store || exit 1
+ @go test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./utils || exit 1
+ @go test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./web || exit 1
build:
@go build $(GOFLAGS) ./...
diff --git a/api/api_test.go b/api/api_test.go
index ffa951f6d..b407c2a5e 100644
--- a/api/api_test.go
+++ b/api/api_test.go
@@ -5,6 +5,7 @@ package api
import (
"github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
)
@@ -27,7 +28,7 @@ func SetupBenchmark() (*model.Team, *model.User, *model.Channel) {
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "benchmark@test.com", FullName: "Mr. Benchmarker", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Domain, user.Email, "pwd")
channel := &model.Channel{DisplayName: "Benchmark Channel", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel = Client.Must(Client.CreateChannel(channel)).Data.(*model.Channel)
diff --git a/api/auto_users.go b/api/auto_users.go
index 1874ffbec..493ec5c17 100644
--- a/api/auto_users.go
+++ b/api/auto_users.go
@@ -5,6 +5,7 @@ package api
import (
"github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
)
@@ -45,7 +46,7 @@ func CreateBasicUser(client *model.Client) *model.AppError {
if err != nil {
return err
}
- Srv.Store.User().VerifyEmail(result.Data.(*model.User).Id)
+ store.Must(Srv.Store.User().VerifyEmail(result.Data.(*model.User).Id))
}
return nil
}
@@ -72,7 +73,7 @@ func (cfg *AutoUserCreator) createRandomUser() (*model.User, bool) {
return nil, false
}
// We need to cheat to verify the user's email
- Srv.Store.User().VerifyEmail(result.Data.(*model.User).Id)
+ store.Must(Srv.Store.User().VerifyEmail(result.Data.(*model.User).Id))
return result.Data.(*model.User), true
}
diff --git a/api/channel_benchmark_test.go b/api/channel_benchmark_test.go
index bb00da138..461a7ed3a 100644
--- a/api/channel_benchmark_test.go
+++ b/api/channel_benchmark_test.go
@@ -5,6 +5,7 @@ package api
import (
"github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
"testing"
)
@@ -139,7 +140,7 @@ func BenchmarkJoinChannel(b *testing.B) {
// Secondary test user to join channels created by primary test user
user := &model.User{TeamId: team.Id, Email: model.NewId() + "random@test.com", FullName: "That Guy", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Domain, user.Email, "pwd")
// Benchmark Start
diff --git a/api/channel_test.go b/api/channel_test.go
index dfae840dc..ff09ab4bc 100644
--- a/api/channel_test.go
+++ b/api/channel_test.go
@@ -5,8 +5,10 @@ package api
import (
"github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/store"
"net/http"
"testing"
+ "time"
)
func TestCreateChannel(t *testing.T) {
@@ -20,7 +22,7 @@ func TestCreateChannel(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Domain, user.Email, "pwd")
@@ -88,11 +90,11 @@ func TestCreateDirectChannel(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user2.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Domain, user.Email, "pwd")
@@ -143,15 +145,15 @@ func TestUpdateChannel(t *testing.T) {
userTeamAdmin := &model.User{TeamId: team.Id, Email: team.Email, FullName: "Corey Hulen", Password: "pwd"}
userTeamAdmin = Client.Must(Client.CreateUser(userTeamAdmin, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(userTeamAdmin.Id)
+ store.Must(Srv.Store.User().VerifyEmail(userTeamAdmin.Id))
userChannelAdmin := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
userChannelAdmin = Client.Must(Client.CreateUser(userChannelAdmin, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(userChannelAdmin.Id)
+ store.Must(Srv.Store.User().VerifyEmail(userChannelAdmin.Id))
userStd := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
userStd = Client.Must(Client.CreateUser(userStd, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(userStd.Id)
+ store.Must(Srv.Store.User().VerifyEmail(userStd.Id))
userStd.Roles = ""
Client.LoginByEmail(team.Domain, userChannelAdmin.Email, "pwd")
@@ -214,7 +216,7 @@ func TestUpdateChannelDesc(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Domain, user.Email, "pwd")
@@ -257,7 +259,7 @@ func TestUpdateChannelDesc(t *testing.T) {
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user2.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Domain, user2.Email, "pwd")
@@ -276,7 +278,7 @@ func TestGetChannel(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Domain, user.Email, "pwd")
@@ -318,7 +320,7 @@ func TestGetMoreChannel(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
@@ -330,7 +332,7 @@ func TestGetMoreChannel(t *testing.T) {
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user2.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Domain, user2.Email, "pwd")
@@ -362,7 +364,7 @@ func TestJoinChannel(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
@@ -374,7 +376,7 @@ func TestJoinChannel(t *testing.T) {
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user2.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Domain, user2.Email, "pwd")
@@ -406,7 +408,7 @@ func TestLeaveChannel(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
@@ -418,7 +420,7 @@ func TestLeaveChannel(t *testing.T) {
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user2.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Domain, user2.Email, "pwd")
@@ -455,11 +457,11 @@ func TestDeleteChannel(t *testing.T) {
userTeamAdmin := &model.User{TeamId: team.Id, Email: team.Email, FullName: "Corey Hulen", Password: "pwd"}
userTeamAdmin = Client.Must(Client.CreateUser(userTeamAdmin, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(userTeamAdmin.Id)
+ store.Must(Srv.Store.User().VerifyEmail(userTeamAdmin.Id))
userChannelAdmin := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
userChannelAdmin = Client.Must(Client.CreateUser(userChannelAdmin, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(userChannelAdmin.Id)
+ store.Must(Srv.Store.User().VerifyEmail(userChannelAdmin.Id))
Client.LoginByEmail(team.Domain, userChannelAdmin.Email, "pwd")
@@ -491,7 +493,7 @@ func TestDeleteChannel(t *testing.T) {
userStd := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
userStd = Client.Must(Client.CreateUser(userStd, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(userStd.Id)
+ store.Must(Srv.Store.User().VerifyEmail(userStd.Id))
Client.LoginByEmail(team.Domain, userStd.Email, "pwd")
@@ -525,7 +527,7 @@ func TestGetChannelExtraInfo(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Domain, user.Email, "pwd")
@@ -546,7 +548,7 @@ func TestAddChannelMember(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
@@ -555,7 +557,7 @@ func TestAddChannelMember(t *testing.T) {
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user2.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user2.Id))
if _, err := Client.AddChannelMember(channel1.Id, user2.Id); err != nil {
t.Fatal(err)
@@ -604,11 +606,11 @@ func TestRemoveChannelMember(t *testing.T) {
userTeamAdmin := &model.User{TeamId: team.Id, Email: team.Email, FullName: "Corey Hulen", Password: "pwd"}
userTeamAdmin = Client.Must(Client.CreateUser(userTeamAdmin, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(userTeamAdmin.Id)
+ store.Must(Srv.Store.User().VerifyEmail(userTeamAdmin.Id))
userChannelAdmin := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
userChannelAdmin = Client.Must(Client.CreateUser(userChannelAdmin, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(userChannelAdmin.Id)
+ store.Must(Srv.Store.User().VerifyEmail(userChannelAdmin.Id))
Client.LoginByEmail(team.Domain, userChannelAdmin.Email, "pwd")
@@ -624,7 +626,7 @@ func TestRemoveChannelMember(t *testing.T) {
userStd := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
userStd = Client.Must(Client.CreateUser(userStd, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(userStd.Id)
+ store.Must(Srv.Store.User().VerifyEmail(userStd.Id))
Client.Must(Client.AddChannelMember(channel1.Id, userStd.Id))
@@ -674,7 +676,7 @@ func TestUpdateNotifyLevel(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Domain, user.Email, "pwd")
@@ -687,6 +689,7 @@ func TestUpdateNotifyLevel(t *testing.T) {
data["notify_level"] = model.CHANNEL_NOTIFY_MENTION
timeBeforeUpdate := model.GetMillis()
+ time.Sleep(100 * time.Millisecond)
if _, err := Client.UpdateNotifyLevel(data); err != nil {
t.Fatal(err)
@@ -755,7 +758,7 @@ func TestFuzzyChannel(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Domain, user.Email, "pwd")
diff --git a/api/command_test.go b/api/command_test.go
index 5b7734628..624c445e6 100644
--- a/api/command_test.go
+++ b/api/command_test.go
@@ -5,6 +5,7 @@ package api
import (
"github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/store"
"testing"
)
@@ -16,7 +17,7 @@ func TestSuggestRootCommands(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
@@ -59,7 +60,7 @@ func TestLogoutCommands(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
@@ -77,7 +78,7 @@ func TestJoinCommands(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
@@ -91,7 +92,7 @@ func TestJoinCommands(t *testing.T) {
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
data := make(map[string]string)
data["user_id"] = user2.Id
diff --git a/api/file_test.go b/api/file_test.go
index 6fd231165..e334fd6e5 100644
--- a/api/file_test.go
+++ b/api/file_test.go
@@ -9,6 +9,7 @@ import (
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/s3"
"github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
"io"
"mime/multipart"
@@ -28,7 +29,7 @@ func TestUploadFile(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
@@ -115,7 +116,7 @@ func TestGetFile(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
@@ -177,7 +178,7 @@ func TestGetFile(t *testing.T) {
user2 := &model.User{TeamId: team2.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user2.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user2.Id))
newProps := make(map[string]string)
newProps["filename"] = filenames[0]
@@ -262,11 +263,11 @@ func TestGetPublicLink(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user2.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
diff --git a/api/post_test.go b/api/post_test.go
index 03f70bff7..970307759 100644
--- a/api/post_test.go
+++ b/api/post_test.go
@@ -5,6 +5,7 @@ package api
import (
"github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
"net/http"
"testing"
@@ -22,11 +23,11 @@ func TestCreatePost(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user2.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
@@ -104,7 +105,7 @@ func TestCreatePost(t *testing.T) {
user3 := &model.User{TeamId: team2.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user3.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user3.Id))
Client.LoginByEmail(team2.Domain, user3.Email, "pwd")
@@ -133,11 +134,11 @@ func TestCreateValetPost(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user2.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
@@ -189,7 +190,7 @@ func TestCreateValetPost(t *testing.T) {
user3 := &model.User{TeamId: team2.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user3.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user3.Id))
Client.LoginByEmail(team2.Domain, user3.Email, "pwd")
@@ -225,11 +226,11 @@ func TestUpdatePost(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user2.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
@@ -293,7 +294,7 @@ func TestGetPosts(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
@@ -358,7 +359,7 @@ func TestSearchPosts(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
@@ -404,7 +405,7 @@ func TestSearchHashtagPosts(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
@@ -435,7 +436,7 @@ func TestGetPostsCache(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
@@ -484,7 +485,7 @@ func TestDeletePosts(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
@@ -532,7 +533,7 @@ func TestEmailMention(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: "corey@test.com", FullName: "Bob Bobby", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
@@ -554,7 +555,7 @@ func TestFuzzyPosts(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Domain, user.Email, "pwd")
diff --git a/api/team_test.go b/api/team_test.go
index bb77d43a0..2bf3219e4 100644
--- a/api/team_test.go
+++ b/api/team_test.go
@@ -6,6 +6,7 @@ package api
import (
"fmt"
"github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
"strings"
"testing"
@@ -78,7 +79,7 @@ func TestCreateTeam(t *testing.T) {
user := &model.User{TeamId: rteam.Data.(*model.Team).Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Domain, user.Email, "pwd")
@@ -115,7 +116,7 @@ func TestFindTeamByEmail(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
if r1, err := Client.FindTeams(user.Email); err != nil {
t.Fatal(err)
@@ -143,7 +144,7 @@ func TestFindTeamByDomain(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
if r1, err := Client.FindTeamByDomain(team.Domain, false); err != nil {
t.Fatal(err)
@@ -183,7 +184,7 @@ func TestFindTeamByEmailSend(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
if _, err := Client.FindTeamsSendEmail(user.Email); err != nil {
t.Fatal(err)
@@ -207,7 +208,7 @@ func TestInviteMembers(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Domain, user.Email, "pwd")
@@ -236,11 +237,11 @@ func TestUpdateTeamName(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: "test@nowhere.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user2.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Domain, user2.Email, "pwd")
@@ -311,7 +312,7 @@ func TestGetMyTeam(t *testing.T) {
user := model.User{TeamId: rteam.Data.(*model.Team).Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
ruser, _ := Client.CreateUser(&user, "")
- Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id)
+ store.Must(Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
Client.LoginByEmail(team.Domain, user.Email, user.Password)
@@ -338,18 +339,18 @@ func TestUpdateValetFeature(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: "test@nowhere.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user2.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user2.Id))
team2 := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team2 = Client.Must(Client.CreateTeam(team2)).Data.(*model.Team)
user3 := &model.User{TeamId: team2.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user3.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user3.Id))
Client.LoginByEmail(team.Domain, user2.Email, "pwd")
diff --git a/api/user_test.go b/api/user_test.go
index 92ab216aa..6e99ab930 100644
--- a/api/user_test.go
+++ b/api/user_test.go
@@ -9,6 +9,7 @@ import (
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/s3"
"github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
"image"
"image/color"
@@ -99,7 +100,7 @@ func TestLogin(t *testing.T) {
user := model.User{TeamId: rteam.Data.(*model.Team).Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
ruser, _ := Client.CreateUser(&user, "")
- Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id)
+ store.Must(Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
if result, err := Client.LoginById(ruser.Data.(*model.User).Id, user.Password); err != nil {
t.Fatal(err)
@@ -168,7 +169,7 @@ func TestSessions(t *testing.T) {
user := model.User{TeamId: rteam.Data.(*model.Team).Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
ruser := Client.Must(Client.CreateUser(&user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(ruser.Id)
+ store.Must(Srv.Store.User().VerifyEmail(ruser.Id))
deviceId := model.NewId()
Client.LoginByEmailWithDevice(team.Domain, user.Email, user.Password, deviceId)
@@ -225,11 +226,11 @@ func TestGetUser(t *testing.T) {
user := model.User{TeamId: rteam.Data.(*model.Team).Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
ruser, _ := Client.CreateUser(&user, "")
- Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id)
+ store.Must(Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
user2 := model.User{TeamId: rteam.Data.(*model.Team).Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
ruser2, _ := Client.CreateUser(&user2, "")
- Srv.Store.User().VerifyEmail(ruser2.Data.(*model.User).Id)
+ store.Must(Srv.Store.User().VerifyEmail(ruser2.Data.(*model.User).Id))
Client.LoginByEmail(team.Domain, user.Email, user.Password)
@@ -296,11 +297,13 @@ func TestGetAudits(t *testing.T) {
user := model.User{TeamId: rteam.Data.(*model.Team).Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
ruser, _ := Client.CreateUser(&user, "")
- Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id)
+ store.Must(Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
+
+ time.Sleep(100 * time.Millisecond)
Client.LoginByEmail(team.Domain, user.Email, user.Password)
- time.Sleep(500 * time.Millisecond)
+ time.Sleep(100 * time.Millisecond)
if result, err := Client.GetAudits(ruser.Data.(*model.User).Id, ""); err != nil {
t.Fatal(err)
@@ -347,7 +350,7 @@ func TestUserCreateImage(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Domain, user.Email, "pwd")
@@ -363,7 +366,7 @@ func TestUserUploadProfileImage(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
if utils.IsS3Configured() {
@@ -462,7 +465,7 @@ func TestUserUpdate(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", FullName: "Corey Hulen", Password: "pwd", LastActivityAt: time1, LastPingAt: time1, Roles: ""}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
if _, err := Client.UpdateUser(user); err == nil {
t.Fatal("Should have errored")
@@ -470,8 +473,12 @@ func TestUserUpdate(t *testing.T) {
Client.LoginByEmail(team.Domain, user.Email, "pwd")
+ time.Sleep(100 * time.Millisecond)
+
time2 := model.GetMillis()
+ time.Sleep(100 * time.Millisecond)
+
user.FullName = "Jim Jimmy"
user.TeamId = "12345678901234567890123456"
user.LastActivityAt = time2
@@ -488,10 +495,10 @@ func TestUserUpdate(t *testing.T) {
if result.Data.(*model.User).TeamId != team.Id {
t.Fatal("TeamId should not have updated")
}
- if result.Data.(*model.User).LastActivityAt != time1 {
+ if result.Data.(*model.User).LastActivityAt == time2 {
t.Fatal("LastActivityAt should not have updated")
}
- if result.Data.(*model.User).LastPingAt != time1 {
+ if result.Data.(*model.User).LastPingAt == time2 {
t.Fatal("LastPingAt should not have updated")
}
if result.Data.(*model.User).Roles != "" {
@@ -514,7 +521,7 @@ func TestUserUpdate(t *testing.T) {
user2 := &model.User{TeamId: team.Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user2.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Domain, user2.Email, "pwd")
@@ -533,7 +540,7 @@ func TestUserUpdatePassword(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
if _, err := Client.UpdateUserPassword(user.Id, "pwd", "newpwd"); err == nil {
t.Fatal("Should have errored")
@@ -592,11 +599,11 @@ func TestUserUpdateRoles(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: "test@nowhere.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
user2 := &model.User{TeamId: team.Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user2.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user2.Id))
data := make(map[string]string)
data["user_id"] = user.Id
@@ -617,7 +624,7 @@ func TestUserUpdateRoles(t *testing.T) {
user3 := &model.User{TeamId: team2.Id, Email: "test@nowhere.com", FullName: "Corey Hulen", Password: "pwd"}
user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user3.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user3.Id))
Client.LoginByEmail(team2.Domain, user3.Email, "pwd")
@@ -661,11 +668,11 @@ func TestUserUpdateActive(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: "test@nowhere.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
user2 := &model.User{TeamId: team.Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user2.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user2.Id))
if _, err := Client.UpdateActive(user.Id, false); err == nil {
t.Fatal("Should have errored, not logged in")
@@ -682,7 +689,7 @@ func TestUserUpdateActive(t *testing.T) {
user3 := &model.User{TeamId: team2.Id, Email: "test@nowhere.com", FullName: "Corey Hulen", Password: "pwd"}
user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user3.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user3.Id))
Client.LoginByEmail(team2.Domain, user3.Email, "pwd")
@@ -725,7 +732,7 @@ func TestSendPasswordReset(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
data := make(map[string]string)
data["email"] = user.Email
@@ -765,7 +772,7 @@ func TestResetPassword(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
data := make(map[string]string)
data["new_password"] = "newpwd"
@@ -849,7 +856,7 @@ func TestUserUpdateNotify(t *testing.T) {
user := &model.User{TeamId: team.Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", FullName: "Corey Hulen", Password: "pwd", Roles: ""}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user.Id))
data := make(map[string]string)
data["user_id"] = user.Id
@@ -943,7 +950,7 @@ func TestStatuses(t *testing.T) {
user := model.User{TeamId: rteam.Data.(*model.Team).Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
ruser := Client.Must(Client.CreateUser(&user, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(ruser.Id)
+ store.Must(Srv.Store.User().VerifyEmail(ruser.Id))
Client.LoginByEmail(team.Domain, user.Email, user.Password)
diff --git a/api/web_socket_test.go b/api/web_socket_test.go
index 15bc3baeb..4cb49220f 100644
--- a/api/web_socket_test.go
+++ b/api/web_socket_test.go
@@ -6,6 +6,7 @@ package api
import (
"github.com/gorilla/websocket"
"github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
"net/http"
"testing"
@@ -21,7 +22,7 @@ func TestSocket(t *testing.T) {
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user1.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
Client.LoginByEmail(team.Domain, user1.Email, "pwd")
channel1 := &model.Channel{DisplayName: "Test Web Scoket 1", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
@@ -40,7 +41,7 @@ func TestSocket(t *testing.T) {
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", FullName: "Corey Hulen", Password: "pwd"}
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
- Srv.Store.User().VerifyEmail(user2.Id)
+ store.Must(Srv.Store.User().VerifyEmail(user2.Id))
Client.LoginByEmail(team.Domain, user2.Email, "pwd")
header2 := http.Header{}
diff --git a/config/config.json b/config/config.json
index e38f1701a..b0a019e8d 100644
--- a/config/config.json
+++ b/config/config.json
@@ -1,7 +1,7 @@
{
"LogSettings": {
"ConsoleEnable": true,
- "ConsoleLevel": "INFO",
+ "ConsoleLevel": "DEBUG",
"FileEnable": true,
"FileLevel": "INFO",
"FileFormat": "",
diff --git a/store/sql_audit_store_test.go b/store/sql_audit_store_test.go
index 3e6f22730..4d804d150 100644
--- a/store/sql_audit_store_test.go
+++ b/store/sql_audit_store_test.go
@@ -6,17 +6,24 @@ package store
import (
"github.com/mattermost/platform/model"
"testing"
+ "time"
)
func TestSqlAuditStore(t *testing.T) {
Setup()
audit := &model.Audit{UserId: model.NewId(), IpAddress: "ipaddress", Action: "Action"}
- <-store.Audit().Save(audit)
- <-store.Audit().Save(audit)
- <-store.Audit().Save(audit)
+ Must(store.Audit().Save(audit))
+ time.Sleep(100 * time.Millisecond)
+ Must(store.Audit().Save(audit))
+ time.Sleep(100 * time.Millisecond)
+ Must(store.Audit().Save(audit))
+ time.Sleep(100 * time.Millisecond)
audit.ExtraInfo = "extra"
- <-store.Audit().Save(audit)
+ time.Sleep(100 * time.Millisecond)
+ Must(store.Audit().Save(audit))
+
+ time.Sleep(100 * time.Millisecond)
c := store.Audit().Get(audit.UserId, 100)
result := <-c
diff --git a/store/sql_channel_store_test.go b/store/sql_channel_store_test.go
index ce4ff75f0..9821e9ad0 100644
--- a/store/sql_channel_store_test.go
+++ b/store/sql_channel_store_test.go
@@ -6,6 +6,7 @@ package store
import (
"github.com/mattermost/platform/model"
"testing"
+ "time"
)
func TestChannelStoreSave(t *testing.T) {
@@ -55,7 +56,12 @@ func TestChannelStoreUpdate(t *testing.T) {
o1.DisplayName = "Name"
o1.Name = "a" + model.NewId() + "b"
o1.Type = model.CHANNEL_OPEN
- <-store.Channel().Save(&o1)
+
+ if err := (<-store.Channel().Save(&o1)).Err; err != nil {
+ t.Fatal(err)
+ }
+
+ time.Sleep(100 * time.Millisecond)
if err := (<-store.Channel().Update(&o1)).Err; err != nil {
t.Fatal(err)
@@ -80,7 +86,7 @@ func TestChannelStoreGet(t *testing.T) {
o1.DisplayName = "Name"
o1.Name = "a" + model.NewId() + "b"
o1.Type = model.CHANNEL_OPEN
- <-store.Channel().Save(&o1)
+ Must(store.Channel().Save(&o1))
if r1 := <-store.Channel().Get(o1.Id); r1.Err != nil {
t.Fatal(r1.Err)
@@ -103,40 +109,40 @@ func TestChannelStoreDelete(t *testing.T) {
o1.DisplayName = "Channel1"
o1.Name = "a" + model.NewId() + "b"
o1.Type = model.CHANNEL_OPEN
- <-store.Channel().Save(&o1)
+ Must(store.Channel().Save(&o1))
o2 := model.Channel{}
o2.TeamId = o1.TeamId
o2.DisplayName = "Channel2"
o2.Name = "a" + model.NewId() + "b"
o2.Type = model.CHANNEL_OPEN
- <-store.Channel().Save(&o2)
+ Must(store.Channel().Save(&o2))
o3 := model.Channel{}
o3.TeamId = o1.TeamId
o3.DisplayName = "Channel3"
o3.Name = "a" + model.NewId() + "b"
o3.Type = model.CHANNEL_OPEN
- <-store.Channel().Save(&o3)
+ Must(store.Channel().Save(&o3))
o4 := model.Channel{}
o4.TeamId = o1.TeamId
o4.DisplayName = "Channel4"
o4.Name = "a" + model.NewId() + "b"
o4.Type = model.CHANNEL_OPEN
- <-store.Channel().Save(&o4)
+ Must(store.Channel().Save(&o4))
m1 := model.ChannelMember{}
m1.ChannelId = o1.Id
m1.UserId = model.NewId()
m1.NotifyLevel = model.CHANNEL_NOTIFY_ALL
- <-store.Channel().SaveMember(&m1)
+ Must(store.Channel().SaveMember(&m1))
m2 := model.ChannelMember{}
m2.ChannelId = o2.Id
m2.UserId = m1.UserId
m2.NotifyLevel = model.CHANNEL_NOTIFY_ALL
- <-store.Channel().SaveMember(&m2)
+ Must(store.Channel().SaveMember(&m2))
if r := <-store.Channel().Delete(o1.Id, model.GetMillis()); r.Err != nil {
t.Fatal(r.Err)
@@ -173,7 +179,7 @@ func TestChannelStoreGetByName(t *testing.T) {
o1.DisplayName = "Name"
o1.Name = "a" + model.NewId() + "b"
o1.Type = model.CHANNEL_OPEN
- <-store.Channel().Save(&o1)
+ Must(store.Channel().Save(&o1))
if r1 := <-store.Channel().GetByName(o1.TeamId, o1.Name); r1.Err != nil {
t.Fatal(r1.Err)
@@ -195,32 +201,32 @@ func TestChannelMemberStore(t *testing.T) {
u1.TeamId = model.NewId()
u1.Email = model.NewId()
u1.FullName = model.NewId()
- <-store.User().Save(&u1)
+ Must(store.User().Save(&u1))
u2 := model.User{}
u2.TeamId = model.NewId()
u2.Email = model.NewId()
u2.FullName = model.NewId()
- <-store.User().Save(&u2)
+ Must(store.User().Save(&u2))
o1 := model.ChannelMember{}
o1.ChannelId = model.NewId()
o1.UserId = u1.Id
o1.NotifyLevel = model.CHANNEL_NOTIFY_ALL
- <-store.Channel().SaveMember(&o1)
+ Must(store.Channel().SaveMember(&o1))
o2 := model.ChannelMember{}
o2.ChannelId = o1.ChannelId
o2.UserId = u2.Id
o2.NotifyLevel = model.CHANNEL_NOTIFY_ALL
- <-store.Channel().SaveMember(&o2)
+ Must(store.Channel().SaveMember(&o2))
members := (<-store.Channel().GetMembers(o1.ChannelId)).Data.([]model.ChannelMember)
if len(members) != 2 {
t.Fatal("should have saved 2 members")
}
- <-store.Channel().RemoveMember(o2.ChannelId, o2.UserId)
+ Must(store.Channel().RemoveMember(o2.ChannelId, o2.UserId))
members = (<-store.Channel().GetMembers(o1.ChannelId)).Data.([]model.ChannelMember)
if len(members) != 1 {
@@ -250,13 +256,13 @@ func TestChannelStorePermissionsTo(t *testing.T) {
o1.DisplayName = "Channel1"
o1.Name = "a" + model.NewId() + "b"
o1.Type = model.CHANNEL_OPEN
- <-store.Channel().Save(&o1)
+ Must(store.Channel().Save(&o1))
m1 := model.ChannelMember{}
m1.ChannelId = o1.Id
m1.UserId = model.NewId()
m1.NotifyLevel = model.CHANNEL_NOTIFY_ALL
- <-store.Channel().SaveMember(&m1)
+ Must(store.Channel().SaveMember(&m1))
count := (<-store.Channel().CheckPermissionsTo(o1.TeamId, o1.Id, m1.UserId)).Data.(int64)
if count != 1 {
@@ -297,7 +303,7 @@ func TestChannelStoreOpenChannelPermissionsTo(t *testing.T) {
o1.DisplayName = "Channel1"
o1.Name = "a" + model.NewId() + "b"
o1.Type = model.CHANNEL_OPEN
- <-store.Channel().Save(&o1)
+ Must(store.Channel().Save(&o1))
count := (<-store.Channel().CheckOpenChannelPermissions(o1.TeamId, o1.Id)).Data.(int64)
if count != 1 {
@@ -323,32 +329,32 @@ func TestChannelStoreGetChannels(t *testing.T) {
o2.DisplayName = "Channel2"
o2.Name = "a" + model.NewId() + "b"
o2.Type = model.CHANNEL_OPEN
- <-store.Channel().Save(&o2)
+ Must(store.Channel().Save(&o2))
o1 := model.Channel{}
o1.TeamId = model.NewId()
o1.DisplayName = "Channel1"
o1.Name = "a" + model.NewId() + "b"
o1.Type = model.CHANNEL_OPEN
- <-store.Channel().Save(&o1)
+ Must(store.Channel().Save(&o1))
m1 := model.ChannelMember{}
m1.ChannelId = o1.Id
m1.UserId = model.NewId()
m1.NotifyLevel = model.CHANNEL_NOTIFY_ALL
- <-store.Channel().SaveMember(&m1)
+ Must(store.Channel().SaveMember(&m1))
m2 := model.ChannelMember{}
m2.ChannelId = o1.Id
m2.UserId = model.NewId()
m2.NotifyLevel = model.CHANNEL_NOTIFY_ALL
- <-store.Channel().SaveMember(&m2)
+ Must(store.Channel().SaveMember(&m2))
m3 := model.ChannelMember{}
m3.ChannelId = o2.Id
m3.UserId = model.NewId()
m3.NotifyLevel = model.CHANNEL_NOTIFY_ALL
- <-store.Channel().SaveMember(&m3)
+ Must(store.Channel().SaveMember(&m3))
cresult := <-store.Channel().GetChannels(o1.TeamId, m1.UserId)
list := cresult.Data.(*model.ChannelList)
@@ -366,53 +372,53 @@ func TestChannelStoreGetMoreChannels(t *testing.T) {
o1.DisplayName = "Channel1"
o1.Name = "a" + model.NewId() + "b"
o1.Type = model.CHANNEL_OPEN
- <-store.Channel().Save(&o1)
+ Must(store.Channel().Save(&o1))
o2 := model.Channel{}
o2.TeamId = model.NewId()
o2.DisplayName = "Channel2"
o2.Name = "a" + model.NewId() + "b"
o2.Type = model.CHANNEL_OPEN
- <-store.Channel().Save(&o2)
+ Must(store.Channel().Save(&o2))
m1 := model.ChannelMember{}
m1.ChannelId = o1.Id
m1.UserId = model.NewId()
m1.NotifyLevel = model.CHANNEL_NOTIFY_ALL
- <-store.Channel().SaveMember(&m1)
+ Must(store.Channel().SaveMember(&m1))
m2 := model.ChannelMember{}
m2.ChannelId = o1.Id
m2.UserId = model.NewId()
m2.NotifyLevel = model.CHANNEL_NOTIFY_ALL
- <-store.Channel().SaveMember(&m2)
+ Must(store.Channel().SaveMember(&m2))
m3 := model.ChannelMember{}
m3.ChannelId = o2.Id
m3.UserId = model.NewId()
m3.NotifyLevel = model.CHANNEL_NOTIFY_ALL
- <-store.Channel().SaveMember(&m3)
+ Must(store.Channel().SaveMember(&m3))
o3 := model.Channel{}
o3.TeamId = o1.TeamId
o3.DisplayName = "ChannelA"
o3.Name = "a" + model.NewId() + "b"
o3.Type = model.CHANNEL_OPEN
- <-store.Channel().Save(&o3)
+ Must(store.Channel().Save(&o3))
o4 := model.Channel{}
o4.TeamId = o1.TeamId
o4.DisplayName = "ChannelB"
o4.Name = "a" + model.NewId() + "b"
o4.Type = model.CHANNEL_PRIVATE
- <-store.Channel().Save(&o4)
+ Must(store.Channel().Save(&o4))
o5 := model.Channel{}
o5.TeamId = o1.TeamId
o5.DisplayName = "ChannelC"
o5.Name = "a" + model.NewId() + "b"
o5.Type = model.CHANNEL_PRIVATE
- <-store.Channel().Save(&o5)
+ Must(store.Channel().Save(&o5))
cresult := <-store.Channel().GetMoreChannels(o1.TeamId, m1.UserId)
list := cresult.Data.(*model.ChannelList)
@@ -435,13 +441,13 @@ func TestChannelStoreUpdateLastViewedAt(t *testing.T) {
o1.Name = "a" + model.NewId() + "b"
o1.Type = model.CHANNEL_OPEN
o1.TotalMsgCount = 25
- <-store.Channel().Save(&o1)
+ Must(store.Channel().Save(&o1))
m1 := model.ChannelMember{}
m1.ChannelId = o1.Id
m1.UserId = model.NewId()
m1.NotifyLevel = model.CHANNEL_NOTIFY_ALL
- <-store.Channel().SaveMember(&m1)
+ Must(store.Channel().SaveMember(&m1))
err := (<-store.Channel().UpdateLastViewedAt(m1.ChannelId, m1.UserId)).Err
if err != nil {
@@ -463,13 +469,13 @@ func TestChannelStoreIncrementMentionCount(t *testing.T) {
o1.Name = "a" + model.NewId() + "b"
o1.Type = model.CHANNEL_OPEN
o1.TotalMsgCount = 25
- <-store.Channel().Save(&o1)
+ Must(store.Channel().Save(&o1))
m1 := model.ChannelMember{}
m1.ChannelId = o1.Id
m1.UserId = model.NewId()
m1.NotifyLevel = model.CHANNEL_NOTIFY_ALL
- <-store.Channel().SaveMember(&m1)
+ Must(store.Channel().SaveMember(&m1))
err := (<-store.Channel().IncrementMentionCount(m1.ChannelId, m1.UserId)).Err
if err != nil {
diff --git a/store/sql_post_store_test.go b/store/sql_post_store_test.go
index 13dd6e5ed..d9805eb02 100644
--- a/store/sql_post_store_test.go
+++ b/store/sql_post_store_test.go
@@ -280,7 +280,7 @@ func TestPostStoreGetWithChildren(t *testing.T) {
}
}
- <-store.Post().Delete(o3.Id, model.GetMillis())
+ Must(store.Post().Delete(o3.Id, model.GetMillis()))
if r2 := <-store.Post().Get(o1.Id); r2.Err != nil {
t.Fatal(r2.Err)
@@ -291,7 +291,7 @@ func TestPostStoreGetWithChildren(t *testing.T) {
}
}
- <-store.Post().Delete(o2.Id, model.GetMillis())
+ Must(store.Post().Delete(o2.Id, model.GetMillis()))
if r3 := <-store.Post().Get(o1.Id); r3.Err != nil {
t.Fatal(r3.Err)
@@ -399,7 +399,7 @@ func TestPostStoreSearch(t *testing.T) {
m1.ChannelId = c1.Id
m1.UserId = userId
m1.NotifyLevel = model.CHANNEL_NOTIFY_ALL
- <-store.Channel().SaveMember(&m1)
+ Must(store.Channel().SaveMember(&m1))
c2 := &model.Channel{}
c2.TeamId = teamId
diff --git a/store/sql_session_store_test.go b/store/sql_session_store_test.go
index edb1d4c14..581aff971 100644
--- a/store/sql_session_store_test.go
+++ b/store/sql_session_store_test.go
@@ -26,18 +26,18 @@ func TestSessionGet(t *testing.T) {
s1 := model.Session{}
s1.UserId = model.NewId()
s1.TeamId = model.NewId()
- <-store.Session().Save(&s1)
+ Must(store.Session().Save(&s1))
s2 := model.Session{}
s2.UserId = s1.UserId
s2.TeamId = s1.TeamId
- <-store.Session().Save(&s2)
+ Must(store.Session().Save(&s2))
s3 := model.Session{}
s3.UserId = s1.UserId
s3.TeamId = s1.TeamId
s3.ExpiresAt = 1
- <-store.Session().Save(&s3)
+ Must(store.Session().Save(&s3))
if rs1 := (<-store.Session().Get(s1.Id)); rs1.Err != nil {
t.Fatal(rs1.Err)
@@ -63,7 +63,7 @@ func TestSessionRemove(t *testing.T) {
s1 := model.Session{}
s1.UserId = model.NewId()
s1.TeamId = model.NewId()
- <-store.Session().Save(&s1)
+ Must(store.Session().Save(&s1))
if rs1 := (<-store.Session().Get(s1.Id)); rs1.Err != nil {
t.Fatal(rs1.Err)
@@ -73,7 +73,7 @@ func TestSessionRemove(t *testing.T) {
}
}
- <-store.Session().Remove(s1.Id)
+ Must(store.Session().Remove(s1.Id))
if rs2 := (<-store.Session().Get(s1.Id)); rs2.Err == nil {
t.Fatal("should have been removed")
@@ -86,7 +86,7 @@ func TestSessionRemoveAlt(t *testing.T) {
s1 := model.Session{}
s1.UserId = model.NewId()
s1.TeamId = model.NewId()
- <-store.Session().Save(&s1)
+ Must(store.Session().Save(&s1))
if rs1 := (<-store.Session().Get(s1.Id)); rs1.Err != nil {
t.Fatal(rs1.Err)
@@ -96,7 +96,7 @@ func TestSessionRemoveAlt(t *testing.T) {
}
}
- <-store.Session().Remove(s1.AltId)
+ Must(store.Session().Remove(s1.AltId))
if rs2 := (<-store.Session().Get(s1.Id)); rs2.Err == nil {
t.Fatal("should have been removed")
@@ -117,7 +117,7 @@ func TestSessionStoreUpdateLastActivityAt(t *testing.T) {
s1 := model.Session{}
s1.UserId = model.NewId()
s1.TeamId = model.NewId()
- <-store.Session().Save(&s1)
+ Must(store.Session().Save(&s1))
if err := (<-store.Session().UpdateLastActivityAt(s1.Id, 1234567890)).Err; err != nil {
t.Fatal(err)
diff --git a/store/sql_store.go b/store/sql_store.go
index bef8b4867..a0a1a9f23 100644
--- a/store/sql_store.go
+++ b/store/sql_store.go
@@ -8,9 +8,9 @@ import (
"crypto/aes"
"crypto/cipher"
"crypto/hmac"
+ crand "crypto/rand"
"crypto/sha256"
"crypto/sha512"
- crand "crypto/rand"
dbsql "database/sql"
"encoding/base64"
"encoding/json"
@@ -362,21 +362,21 @@ func decrypt(key []byte, cryptoText string) (string, error) {
ciphertext, err := base64.URLEncoding.DecodeString(cryptoText)
if err != nil {
- return "", err
+ return "", err
}
skey := sha512.Sum512(key)
ekey, akey := skey[:32], skey[32:]
macfn := hmac.New(sha256.New, akey)
if len(ciphertext) < aes.BlockSize+macfn.Size() {
- return "", errors.New("short ciphertext")
+ return "", errors.New("short ciphertext")
}
macfn.Write(ciphertext[aes.BlockSize+macfn.Size():])
expectedMac := macfn.Sum(nil)
- mac := ciphertext[aes.BlockSize:aes.BlockSize+macfn.Size()]
+ mac := ciphertext[aes.BlockSize : aes.BlockSize+macfn.Size()]
if hmac.Equal(expectedMac, mac) != true {
- return "", errors.New("Incorrect MAC for the given ciphertext")
+ return "", errors.New("Incorrect MAC for the given ciphertext")
}
block, err := aes.NewCipher(ekey)
diff --git a/store/sql_team_store_test.go b/store/sql_team_store_test.go
index 1b03b75fd..bd1a7de2e 100644
--- a/store/sql_team_store_test.go
+++ b/store/sql_team_store_test.go
@@ -6,6 +6,7 @@ package store
import (
"github.com/mattermost/platform/model"
"testing"
+ "time"
)
func TestTeamStoreSave(t *testing.T) {
@@ -39,7 +40,11 @@ func TestTeamStoreUpdate(t *testing.T) {
o1.Domain = "a" + model.NewId() + "b"
o1.Email = model.NewId() + "@nowhere.com"
o1.Type = model.TEAM_OPEN
- <-store.Team().Save(&o1)
+ if err := (<-store.Team().Save(&o1)).Err; err != nil {
+ t.Fatal(err)
+ }
+
+ time.Sleep(100 * time.Millisecond)
if err := (<-store.Team().Update(&o1)).Err; err != nil {
t.Fatal(err)
@@ -86,7 +91,7 @@ func TestTeamStoreGet(t *testing.T) {
o1.Domain = "a" + model.NewId() + "b"
o1.Email = model.NewId() + "@nowhere.com"
o1.Type = model.TEAM_OPEN
- <-store.Team().Save(&o1)
+ Must(store.Team().Save(&o1))
if r1 := <-store.Team().Get(o1.Id); r1.Err != nil {
t.Fatal(r1.Err)
@@ -135,12 +140,12 @@ func TestTeamStoreGetForEmail(t *testing.T) {
o1.Domain = "a" + model.NewId() + "b"
o1.Email = model.NewId() + "@nowhere.com"
o1.Type = model.TEAM_OPEN
- <-store.Team().Save(&o1)
+ Must(store.Team().Save(&o1))
u1 := model.User{}
u1.TeamId = o1.Id
u1.Email = model.NewId()
- <-store.User().Save(&u1)
+ Must(store.User().Save(&u1))
if r1 := <-store.Team().GetTeamsForEmail(u1.Email); r1.Err != nil {
t.Fatal(r1.Err)
diff --git a/store/sql_user_store.go b/store/sql_user_store.go
index abb8f2781..bcaff1487 100644
--- a/store/sql_user_store.go
+++ b/store/sql_user_store.go
@@ -137,7 +137,7 @@ func (us SqlUserStore) Update(user *model.User, allowRoleActiveUpdate bool) Stor
if count, err := us.GetMaster().Update(user); err != nil {
result.Err = model.NewAppError("SqlUserStore.Update", "We encounted an error updating the account", "user_id="+user.Id+", "+err.Error())
} else if count != 1 {
- result.Err = model.NewAppError("SqlUserStore.Update", "We couldn't update the account", "user_id="+user.Id)
+ result.Err = model.NewAppError("SqlUserStore.Update", "We couldn't update the account", fmt.Sprintf("user_id=%v, count=%v", user.Id, count))
} else {
result.Data = [2]*model.User{user, oldUser}
}
diff --git a/store/sql_user_store_test.go b/store/sql_user_store_test.go
index 4231920a5..f8dae0021 100644
--- a/store/sql_user_store_test.go
+++ b/store/sql_user_store_test.go
@@ -64,7 +64,7 @@ func TestUserStoreUpdate(t *testing.T) {
u1 := model.User{}
u1.TeamId = model.NewId()
u1.Email = model.NewId()
- <-store.User().Save(&u1)
+ Must(store.User().Save(&u1))
if err := (<-store.User().Update(&u1, false)).Err; err != nil {
t.Fatal(err)
@@ -87,7 +87,7 @@ func TestUserStoreUpdateLastPingAt(t *testing.T) {
u1 := model.User{}
u1.TeamId = model.NewId()
u1.Email = model.NewId()
- <-store.User().Save(&u1)
+ Must(store.User().Save(&u1))
if err := (<-store.User().UpdateLastPingAt(u1.Id, 1234567890)).Err; err != nil {
t.Fatal(err)
@@ -109,7 +109,7 @@ func TestUserStoreUpdateLastActivityAt(t *testing.T) {
u1 := model.User{}
u1.TeamId = model.NewId()
u1.Email = model.NewId()
- <-store.User().Save(&u1)
+ Must(store.User().Save(&u1))
if err := (<-store.User().UpdateLastActivityAt(u1.Id, 1234567890)).Err; err != nil {
t.Fatal(err)
@@ -131,12 +131,12 @@ func TestUserStoreUpdateUserAndSessionActivity(t *testing.T) {
u1 := model.User{}
u1.TeamId = model.NewId()
u1.Email = model.NewId()
- <-store.User().Save(&u1)
+ Must(store.User().Save(&u1))
s1 := model.Session{}
s1.UserId = u1.Id
s1.TeamId = u1.TeamId
- <-store.Session().Save(&s1)
+ Must(store.Session().Save(&s1))
if err := (<-store.User().UpdateUserAndSessionActivity(u1.Id, s1.Id, 1234567890)).Err; err != nil {
t.Fatal(err)
@@ -166,7 +166,7 @@ func TestUserStoreGet(t *testing.T) {
u1 := model.User{}
u1.TeamId = model.NewId()
u1.Email = model.NewId()
- <-store.User().Save(&u1)
+ Must(store.User().Save(&u1))
if r1 := <-store.User().Get(u1.Id); r1.Err != nil {
t.Fatal(r1.Err)
@@ -187,12 +187,12 @@ func TestUserStoreGetProfiles(t *testing.T) {
u1 := model.User{}
u1.TeamId = model.NewId()
u1.Email = model.NewId()
- <-store.User().Save(&u1)
+ Must(store.User().Save(&u1))
u2 := model.User{}
u2.TeamId = u1.TeamId
u2.Email = model.NewId()
- <-store.User().Save(&u2)
+ Must(store.User().Save(&u2))
if r1 := <-store.User().GetProfiles(u1.TeamId); r1.Err != nil {
t.Fatal(r1.Err)
@@ -222,7 +222,7 @@ func TestUserStoreGetByEmail(t *testing.T) {
u1 := model.User{}
u1.TeamId = model.NewId()
u1.Email = model.NewId()
- <-store.User().Save(&u1)
+ Must(store.User().Save(&u1))
if err := (<-store.User().GetByEmail(u1.TeamId, u1.Email)).Err; err != nil {
t.Fatal(err)
@@ -240,7 +240,7 @@ func TestUserStoreGetByUsername(t *testing.T) {
u1.TeamId = model.NewId()
u1.Email = model.NewId()
u1.Username = model.NewId()
- <-store.User().Save(&u1)
+ Must(store.User().Save(&u1))
if err := (<-store.User().GetByUsername(u1.TeamId, u1.Username)).Err; err != nil {
t.Fatal(err)
@@ -257,7 +257,7 @@ func TestUserStoreUpdatePassword(t *testing.T) {
u1 := model.User{}
u1.TeamId = model.NewId()
u1.Email = model.NewId()
- <-store.User().Save(&u1)
+ Must(store.User().Save(&u1))
hashedPassword := model.HashPassword("newpwd")
diff --git a/store/store.go b/store/store.go
index 8d4b49b6e..070ee0562 100644
--- a/store/store.go
+++ b/store/store.go
@@ -14,6 +14,15 @@ type StoreResult struct {
type StoreChannel chan StoreResult
+func Must(sc StoreChannel) interface{} {
+ r := <-sc
+ if r.Err != nil {
+ panic(r.Err)
+ }
+
+ return r.Data
+}
+
type Store interface {
Team() TeamStore
Channel() ChannelStore