%PDF- %PDF-
Direktori : /home/waritko/go/src/github.com/odeke-em/drive/src/ |
Current File : //home/waritko/go/src/github.com/odeke-em/drive/src/misc_test.go |
// Copyright 2016 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package drive import ( "fmt" "reflect" "runtime" "strings" "testing" "time" "google.golang.org/api/googleapi" ) func callerFilepath() string { _, p, _, _ := runtime.Caller(1) return p } func TestRemoteOpToChangerTranslator(t *testing.T) { g := &Commands{} now := time.Now() cases := []struct { change *Change name string wantedFn func(*Change) error }{ {change: &Change{Src: nil, Dest: nil}, wantedFn: nil, name: "nil"}, {change: &Change{Src: &File{}, Dest: &File{}}, wantedFn: nil, name: "nil"}, {change: &Change{Src: &File{}, Dest: nil}, wantedFn: g.remoteAdd, name: "remoteAdd"}, {change: &Change{Src: nil, Dest: &File{}}, wantedFn: g.remoteTrash, name: "remoteTrash"}, { change: &Change{ Dest: &File{ModTime: now}, Src: &File{ModTime: now.Add(time.Hour)}, }, wantedFn: g.remoteMod, name: "remoteMod", }, { change: &Change{ Dest: &File{ModTime: now}, Src: &File{ModTime: now}, }, wantedFn: nil, name: "noop", }, } for _, tc := range cases { got := remoteOpToChangerTranslator(g, tc.change) vptr1 := reflect.ValueOf(got).Pointer() vptr2 := reflect.ValueOf(tc.wantedFn).Pointer() if vptr1 != vptr2 { t.Errorf("expected %q expected (%p) got (%p)", tc.name, tc.wantedFn, got) } } } func TestLocalOpToChangerTranslator(t *testing.T) { g := &Commands{} now := time.Now() cases := []struct { change *Change name string wantedFn func(*Change, []string) error }{ {change: &Change{Src: nil, Dest: nil}, wantedFn: nil, name: "nil"}, {change: &Change{Src: &File{}, Dest: &File{}}, wantedFn: nil, name: "nil"}, { change: &Change{Src: &File{}, Dest: nil}, wantedFn: g.localAdd, name: "localAdd", }, { change: &Change{Dest: nil, Src: &File{}}, wantedFn: g.localAdd, name: "localAdd", }, { change: &Change{Src: nil, Dest: &File{}}, wantedFn: g.localDelete, name: "localDelete", }, { change: &Change{ Src: &File{ModTime: now}, Dest: &File{ModTime: now.Add(time.Hour)}, }, wantedFn: g.localMod, name: "localMod", }, { change: &Change{ Dest: &File{ModTime: now}, Src: &File{ModTime: now}, }, wantedFn: nil, name: "noop", }, } for _, tc := range cases { got := localOpToChangerTranslator(g, tc.change) vptr1 := reflect.ValueOf(got).Pointer() vptr2 := reflect.ValueOf(tc.wantedFn).Pointer() if vptr1 != vptr2 { t.Errorf("expected %q expected (%p) got (%p)", tc.name, tc.wantedFn, got) } } } func TestRetryableErrorCheck(t *testing.T) { cases := []struct { value interface{} success, retryable bool comment string }{ { value: nil, success: false, retryable: true, comment: "a nil tuple is retryable but not successful", }, { value: t, success: false, retryable: true, comment: "t value is not a tuple, is retryable but not successful", }, { value: &tuple{first: nil, last: nil}, success: true, retryable: false, comment: "last=nil representing a nil error so success, unretryable", }, { value: &tuple{first: nil, last: fmt.Errorf("flux")}, success: false, retryable: true, comment: "last!=nil, non-familiar error so unsuccessful, retryable", }, { value: &tuple{ first: "", last: &googleapi.Error{ Message: "This is an error", }, }, success: false, retryable: false, comment: "last!=nil, familiar error so unsuccessful, retryable:: statusCode undefined", }, { value: &tuple{ first: "", last: &googleapi.Error{ Code: 500, Message: "This is an error", }, }, success: false, retryable: true, comment: "last!=nil, familiar error so unsuccessful, retryable:: statusCode 500", }, { value: &tuple{ first: nil, last: &googleapi.Error{ Code: 401, Message: "401 right here", }, }, success: false, retryable: true, comment: "last!=nil, 401 must be retryable", }, { value: &tuple{ first: nil, last: &googleapi.Error{ Code: 409, Message: "409 right here", }, }, success: false, retryable: false, comment: "last!=nil, 409 is unclassified so unretryable", }, { value: &tuple{ first: nil, last: &googleapi.Error{ Code: 403, Message: "403 right here", }, }, success: false, retryable: true, comment: "last!=nil, 403 is retryable", }, { value: &tuple{ first: nil, last: &googleapi.Error{ Code: 500, Message: MsgErrFileNotMutable, }, }, success: false, retryable: false, comment: "issue #472 FileNotMutable is unretryable", }, { value: &tuple{ first: nil, last: &googleapi.Error{ Code: 500, Message: strings.ToLower(MsgErrFileNotMutable), }, }, success: false, retryable: false, comment: "issue #472 FileNotMutable is unretryable, casefold held", }, { value: &tuple{ first: nil, last: &googleapi.Error{ Code: 501, Message: strings.ToUpper(MsgErrFileNotMutable), }, }, success: false, retryable: false, comment: "issue #472 FileNotMutable is unretryable, casefold held", }, } for _, tc := range cases { success, retryable := retryableErrorCheck(tc.value) if success != tc.success { t.Errorf("%v success got %v expected %v", tc.value, success, tc.success) } if retryable != tc.retryable { t.Errorf("%v retryable got %v expected %v: %q", tc.value, retryable, tc.retryable, tc.comment) } } } func TestDriveIgnore(t *testing.T) { testCases := []struct { clauses []string mustErr bool nilIgnorer bool excludesExpected []string includesExpected []string comment string mustBeIgnored []string mustNotBeIgnored []string }{ {clauses: []string{}, nilIgnorer: true, comment: "no clauses in"}, { clauses: []string{"#this is a comment"}, nilIgnorer: false, comment: "plain commented file", }, { comment: "intentionally unescaped '.'", clauses: []string{".git", ".docx$"}, mustBeIgnored: []string{"bgits", "frogdocx"}, mustNotBeIgnored: []string{"", " ", "frogdocxs"}, }, { comment: "entirely commented, so all clauses should be skipped", clauses: []string{"^#"}, mustBeIgnored: []string{"#patch", "# ", "#", "#Like this one", "#\\.git"}, mustNotBeIgnored: []string{"", " ", "src/misc_test.go"}, }, { comment: "strictly escaped '.'", clauses: []string{"\\.git", "\\.docx$"}, mustBeIgnored: []string{".git", "drive.docx", ".docx"}, mustNotBeIgnored: []string{ "", " ", "frogdocxs", "digit", "drive.docxs", "drive.docxx", "drive.", ".drive", ".docx ", }, }, { comment: "strictly escaped '.'", clauses: []string{"^\\.", "#!\\.driveignore"}, mustBeIgnored: []string{".git", ".driveignore", ".bashrc"}, mustNotBeIgnored: []string{ "", " ", "frogdocxs", "digit", "drive.docxs", "drive.docxx", "drive.", " .drive", "a.docx ", }, }, { comment: "include vs exclude issue #535", clauses: []string{"\\.", "!^\\.docx$", "!\\.bashrc", "#!\\.driveignore"}, mustBeIgnored: []string{".git", "drive.docx", ".docx ", ".driveignore"}, mustNotBeIgnored: []string{ ".docx", ".bashrc", }, }, } for _, tc := range testCases { ignorer, err := ignorerByClause(tc.clauses...) if tc.mustErr { if err == nil { t.Fatalf("expected to err with clause %v comment %q", tc.clauses, tc.comment) } } else if err != nil { t.Fatalf("%v should not err. Got %v", tc.clauses, err) } if tc.nilIgnorer { if ignorer != nil { t.Fatalf("ignorer for (%v)(%q) expected to be nil, got %p", tc.clauses, tc.comment, ignorer) } } else if ignorer == nil { t.Fatalf("ignorer not expected to be nil for (%v) %q", tc.clauses, tc.comment) } if !tc.nilIgnorer && ignorer != nil { for _, expectedPass := range tc.mustBeIgnored { if !ignorer(expectedPass) { t.Errorf("%q: %q must be ignored", tc.comment, expectedPass) } } for _, expectedFail := range tc.mustNotBeIgnored { if ignorer(expectedFail) { t.Errorf("%q: %q must not be ignored", tc.comment, expectedFail) } } } } } func TestReadFile(t *testing.T) { ownFilepath := callerFilepath() comment := ` // A comment right here intentionally put that will self read and consumed. + A follow up right here and now. ` clauses, err := readCommentedFile(ownFilepath, "//") if err != nil { t.Fatalf("%q is currently being run and should be read successfully, instead got err %v", ownFilepath, err) } if len(clauses) < 1 { t.Errorf("expecting at least one line in this file %q", ownFilepath) } restitched := strings.Join(clauses, "\n") if strings.Index(restitched, comment) != -1 { t.Errorf("%q should have been ignored as a comment", comment) } } func TestCustomQuote(t *testing.T) { // https://github.com/golang/go/issues/11511 // https://github.com/odeke-em/drive/issues/250 testCases := []struct { sample, want string }{ { sample: "", want: "\"\"", }, { sample: "全角スペース 含みます/", want: "\"全角スペース 含みます/\"", }, { sample: "this is a test", want: "\"this is a test\"", }, { sample: "this ' is a test", want: "\"this ' is a test\"", }, { sample: "全角スペース\" 含みます/", want: "\"全角スペース\\\" 含みます/\"", }, { sample: "久聞大名 久聞大名", want: "\"久聞大名 久聞大名\"", }, { sample: "Go: для начинающих и профессионалов (18:30)", want: "\"Go: для начинающих и профессионалов (18:30)\"", }, { sample: "Go:\\ для начинающих и профессионалов (18:30)", want: "\"Go:\\\\ для начинающих и профессионалов (18:30)\"", }, } for _, tc := range testCases { got := customQuote(tc.sample) if got != tc.want { t.Errorf("given sample: %v, wanted %v, got %v", tc.sample, tc.want, got) } } } func TestHttpOk(t *testing.T) { testCases := []struct { sample int want bool }{ {sample: 200, want: true}, {sample: 201, want: true}, {sample: 210, want: true}, {sample: 290, want: true}, {sample: 299, want: true}, {sample: -200, want: false}, {sample: -200000000000, want: false}, {sample: 300, want: false}, {sample: 403, want: false}, {sample: 500, want: false}, {sample: 100, want: false}, {sample: 0, want: false}, {sample: -1, want: false}, } for _, tc := range testCases { if got, want := httpOk(tc.sample), tc.want; got != want { t.Errorf("given sample %v, expected %v instead got %v", tc.sample, want, got) } } } func TestCrudToAtoi(t *testing.T) { testCases := []struct { specimen []string want CrudValue comment string }{ { specimen: []string{"create", "delete", "update", "read"}, want: Create | Delete | Update | Read, }, { specimen: []string{"c", "r", "u", "d`"}, want: Create | Read | Update | Delete, comment: "short forms being used", }, { specimen: []string{"trim", "create", "update", "bank`"}, want: Create | Update, }, { specimen: []string{"interfere", "extrict", "influence", "bank`"}, want: None, }, { specimen: []string{"", "", "", "ReAd"}, want: Read, }, { specimen: []string{"", "", "", ""}, want: None, }, } for _, tc := range testCases { if got, want := CrudAtoi(tc.specimen...), tc.want; got != want { t.Errorf("given specimen %v, expected %q instead got %q", tc.specimen, want, got) } } }