11package cmd
22
33import (
4+ "bytes"
5+ "errors"
46 "fmt"
7+ "io/ioutil"
58 "path/filepath"
9+ "strings"
610 "testing"
11+ "time"
712
813 "github.com/vim-volt/volt/internal/testutil"
914 "github.com/vim-volt/volt/lockjson"
1015 "github.com/vim-volt/volt/pathutil"
11- git "gopkg.in/src-d/go-git.v4"
16+ "gopkg.in/src-d/go-git.v4"
17+ "gopkg.in/src-d/go-git.v4/plumbing"
18+ "gopkg.in/src-d/go-git.v4/plumbing/object"
1219)
1320
1421// Checks:
@@ -19,12 +26,21 @@ import (
1926// (E) Directories are copied to `~/.vim/pack/volt/<repos>/`, and the contents are same
2027// (F) Entries are added to lock.json
2128// (G) tags files are created at `~/.vim/pack/volt/<repos>/doc/tags`
29+ // (H) Output contains "! {repos} > install failed"
30+ // (I) Output contains "! {repos} > upgrade failed"
31+ // (J) Output contains "# {repos} > no change"
32+ // (K) Output contains "# {repos} > already exists"
33+ // (L) Output contains "+ {repos} > added repository to current profile"
34+ // (M) Output contains "+ {repos} > installed"
35+ // (N) Output contains "* {repos} > updated lock.json revision ({from}..{to})"
36+ // (O) Output contains "* {repos} > upgraded ({from}..{to})"
37+ // (P) Output contains "{repos}: HEAD and locked revision are different ..."
2238
2339// TODO: Add test cases
2440// * Specify plugins which have dependency plugins without help (A, B, C, D, E, F, !G) / with help (A, B, C, D, E, F, G)
2541// * Specify plugins which have dependency plugins and plugins which have no dependency plugins without help (A, B, C, D, E, F, !G) / with help (A, B, C, D, E, F, G)
2642
27- // Specify one plugin with help (A, B, C, D, E, F, G) / without help (A, B, C, D, E, F, !G)
43+ // Specify one plugin with help (A, B, C, D, E, F, G, M ) / without help (A, B, C, D, E, F, !G, M )
2844func TestVoltGetOnePlugin (t * testing.T ) {
2945 for _ , tt := range []struct {
3046 withHelp bool
@@ -89,7 +105,196 @@ func TestVoltGetOnePlugin(t *testing.T) {
89105 }
90106}
91107
92- // Specify two or more plugins without help (A, B, C, D, E, F, !G) / with help (A, B, C, D, E, F, G)
108+ // (J, K, L, M, N, O, P)
109+ func TestVoltGetMsg (t * testing.T ) {
110+ testGetMatrix (t , func (t * testing.T , strategy string ) {
111+ // =============== setup =============== //
112+
113+ testutil .SetUpEnv (t )
114+ testutil .InstallConfig (t , "strategy-" + strategy + ".toml" )
115+ reposPath := pathutil .ReposPath ("github.com/tyru/caw.vim" )
116+
117+ // ===================================
118+ // Install plugin (installed)
119+ // ===================================
120+
121+ out , err := testutil .RunVolt ("get" , reposPath .String ())
122+ // (A, B)
123+ testutil .SuccessExit (t , out , err )
124+
125+ // (M)
126+ msg := fmt .Sprintf (fmtInstalled , reposPath )
127+ if ! bytes .Contains (out , []byte (msg )) {
128+ t .Errorf ("Output does not contain %q\n %s" , msg , string (out ))
129+ }
130+
131+ // ===================================
132+ // Install again (already exists)
133+ // ===================================
134+
135+ out , err = testutil .RunVolt ("get" , reposPath .String ())
136+ // (A, B)
137+ testutil .SuccessExit (t , out , err )
138+
139+ // (K)
140+ msg = fmt .Sprintf (fmtAlreadyExists , reposPath )
141+ if ! bytes .Contains (out , []byte (msg )) {
142+ t .Errorf ("Output does not contain %q\n %s" , msg , string (out ))
143+ }
144+
145+ // ===================================
146+ // Upgrade one plugin (no change)
147+ // ===================================
148+
149+ out , err = testutil .RunVolt ("get" , "-u" , reposPath .String ())
150+ // (A, B)
151+ testutil .SuccessExit (t , out , err )
152+
153+ // (J)
154+ msg = fmt .Sprintf (fmtNoChange , reposPath )
155+ if ! bytes .Contains (out , []byte (msg )) {
156+ t .Errorf ("Output does not contain %q\n %s" , msg , string (out ))
157+ }
158+
159+ // ===================================
160+ // Remove plugin from current profile
161+ // ===================================
162+
163+ out , err = testutil .RunVolt ("disable" , reposPath .String ())
164+ // (A, B)
165+ testutil .SuccessExit (t , out , err )
166+
167+ // =====================================================================
168+ // Add plugin to current profile (added repository to current profile")
169+ // =====================================================================
170+
171+ out , err = testutil .RunVolt ("get" , reposPath .String ())
172+ // (A, B)
173+ testutil .SuccessExit (t , out , err )
174+
175+ // (L)
176+ msg = fmt .Sprintf (fmtAddedRepos , reposPath )
177+ if ! bytes .Contains (out , []byte (msg )) {
178+ t .Errorf ("Output does not contain %q\n %s" , msg , string (out ))
179+ }
180+
181+ // ================
182+ // Commit on repos
183+ // ================
184+
185+ head , next , err := gitCommitOne (reposPath )
186+ if err != nil {
187+ t .Error ("gitCommitOne() failed: " + err .Error ())
188+ }
189+
190+ // ================================================================
191+ // volt build outputs "HEAD and locked revision are different ..."
192+ // ================================================================
193+
194+ out , err = testutil .RunVolt ("build" )
195+ outstr := string (out )
196+ // (!A, B)
197+ if ! strings .Contains (outstr , "[WARN]" ) && ! strings .Contains (outstr , "[ERROR]" ) {
198+ t .Errorf ("expected error but no error: %s" , outstr )
199+ }
200+ if err != nil {
201+ t .Error ("expected success exit but exited with failure: " + err .Error ())
202+ }
203+
204+ // (P)
205+ for _ , msg := range []string {
206+ string (reposPath ) + ": HEAD and locked revision are different" ,
207+ " HEAD: " + next .String (),
208+ " locked revision: " + head .String (),
209+ " Please run 'volt get -l' to update locked revision." ,
210+ } {
211+ if ! bytes .Contains (out , []byte (msg )) {
212+ t .Errorf ("Output does not contain %q\n %s" , msg , string (out ))
213+ }
214+ }
215+
216+ // ===========================================
217+ // Update lock.json revision
218+ // ===========================================
219+
220+ out , err = testutil .RunVolt ("get" , reposPath .String ())
221+ // (A, B)
222+ testutil .SuccessExit (t , out , err )
223+
224+ // (N)
225+ msg = fmt .Sprintf (fmtRevUpdate , reposPath , head .String (), next .String ())
226+ if ! bytes .Contains (out , []byte (msg )) {
227+ t .Errorf ("Output does not contain %q\n %s" , msg , string (out ))
228+ }
229+
230+ // ================================
231+ // Install again (already exists)
232+ // ================================
233+
234+ out , err = testutil .RunVolt ("get" , reposPath .String ())
235+ // (A, B)
236+ testutil .SuccessExit (t , out , err )
237+
238+ // (K)
239+ msg = fmt .Sprintf (fmtAlreadyExists , reposPath )
240+ if ! bytes .Contains (out , []byte (msg )) {
241+ t .Errorf ("Output does not contain %q\n %s" , msg , string (out ))
242+ }
243+
244+ // ========================================================================
245+ // volt build DOES NOT output "HEAD and locked revision are different ..."
246+ // ========================================================================
247+
248+ out , err = testutil .RunVolt ("build" )
249+ // (A, B)
250+ testutil .SuccessExit (t , out , err )
251+
252+ // (!P)
253+ msg = "HEAD and locked revision are different"
254+ if bytes .Contains (out , []byte (msg )) {
255+ t .Errorf ("Output contains %q\n %s" , msg , string (out ))
256+ }
257+
258+ // ==================================
259+ // "git reset --hard HEAD~2" on repos
260+ // ==================================
261+
262+ prev , _ , err := gitResetHard (reposPath , "HEAD~2" )
263+ if err != nil {
264+ t .Error ("gitResetHard() failed: " + err .Error ())
265+ }
266+
267+ // ===========================================
268+ // Update lock.json revision
269+ // ===========================================
270+
271+ out , err = testutil .RunVolt ("get" , reposPath .String ())
272+ // (A, B)
273+ testutil .SuccessExit (t , out , err )
274+
275+ // (N)
276+ msg = fmt .Sprintf (fmtRevUpdate , reposPath , next .String (), prev .String ())
277+ if ! bytes .Contains (out , []byte (msg )) {
278+ t .Errorf ("Output does not contain %q\n %s" , msg , string (out ))
279+ }
280+
281+ // ================================
282+ // Upgrade plugin (upgraded)
283+ // ================================
284+
285+ out , err = testutil .RunVolt ("get" , "-u" , reposPath .String ())
286+ // (A, B)
287+ testutil .SuccessExit (t , out , err )
288+
289+ // (O)
290+ msg = fmt .Sprintf (fmtUpgraded , reposPath , prev .String (), head .String ())
291+ if ! bytes .Contains (out , []byte (msg )) {
292+ t .Errorf ("Output does not contain %q\n %s" , msg , string (out ))
293+ }
294+ })
295+ }
296+
297+ // Specify two or more plugins without help (A, B, C, D, E, F, !G, M) / with help (A, B, C, D, E, F, G, M)
93298func TestVoltGetTwoOrMorePlugin (t * testing.T ) {
94299 for _ , tt := range []struct {
95300 withHelp bool
@@ -156,6 +361,12 @@ func TestVoltGetTwoOrMorePlugin(t *testing.T) {
156361 t .Error ("doc/tags was created: " + tags )
157362 }
158363 }
364+
365+ // (M)
366+ msg := fmt .Sprintf (fmtInstalled , reposPath )
367+ if ! bytes .Contains (out , []byte (msg )) {
368+ t .Errorf ("Output does not contain %q\n %s" , msg , string (out ))
369+ }
159370 }
160371 })
161372 })
@@ -207,7 +418,7 @@ func TestErrVoltGetInvalidArgs(t *testing.T) {
207418 }
208419}
209420
210- // [error] Specify plugin which does not exist (!A, !B, !C, !D, !E, !F, !G)
421+ // [error] Specify plugin which does not exist (!A, !B, !C, !D, !E, !F, !G, H )
211422func TestErrVoltGetNotFound (t * testing.T ) {
212423 // =============== setup =============== //
213424
@@ -246,6 +457,12 @@ func TestErrVoltGetNotFound(t *testing.T) {
246457 if pathutil .Exists (tags ) {
247458 t .Error ("doc/tags was created: " + tags )
248459 }
460+
461+ // (H)
462+ msg := fmt .Sprintf (fmtInstallFailed , reposPath , "" )
463+ if ! bytes .Contains (out , []byte (msg )) {
464+ t .Errorf ("Output does not contain %q\n %s" , msg , string (out ))
465+ }
249466}
250467
251468func testReposPathWereAdded (t * testing.T , reposPath pathutil.ReposPath ) {
@@ -287,3 +504,72 @@ func testGetMatrix(t *testing.T, f func(*testing.T, string)) {
287504 })
288505 }
289506}
507+
508+ func gitCommitOne (reposPath pathutil.ReposPath ) (prev plumbing.Hash , current plumbing.Hash , err error ) {
509+ var (
510+ relPath = "hello"
511+ content = []byte ("hello world!" )
512+ commitMsg = "hello world"
513+ commitOptions = & git.CommitOptions {
514+ Author : & object.Signature {
515+ Name : "John Doe" ,
516+ 517+ When : time .Now (),
518+ },
519+ }
520+ )
521+
522+ filename := filepath .Join (pathutil .FullReposPath (reposPath ), relPath )
523+ if err = ioutil .WriteFile (filename , content , 0644 ); err != nil {
524+ err = errors .New ("ioutil.WriteFile() failed: " + err .Error ())
525+ return
526+ }
527+ r , err := git .PlainOpen (pathutil .FullReposPath (reposPath ))
528+ if err != nil {
529+ return
530+ }
531+ head , err := r .Head ()
532+ if err != nil {
533+ return
534+ } else {
535+ prev = head .Hash ()
536+ }
537+ w , err := r .Worktree ()
538+ if err != nil {
539+ return
540+ }
541+ _ , err = w .Add (relPath )
542+ if err != nil {
543+ return
544+ }
545+ current , err = w .Commit (commitMsg , commitOptions )
546+ return
547+ }
548+
549+ func gitResetHard (reposPath pathutil.ReposPath , ref string ) (current plumbing.Hash , next plumbing.Hash , err error ) {
550+ r , err := git .PlainOpen (pathutil .FullReposPath (reposPath ))
551+ if err != nil {
552+ return
553+ }
554+ w , err := r .Worktree ()
555+ if err != nil {
556+ return
557+ }
558+ head , err := r .Head ()
559+ if err != nil {
560+ return
561+ } else {
562+ next = head .Hash ()
563+ }
564+ rev , err := r .ResolveRevision (plumbing .Revision (ref ))
565+ if err != nil {
566+ return
567+ } else {
568+ current = * rev
569+ }
570+ err = w .Reset (& git.ResetOptions {
571+ Commit : current ,
572+ Mode : git .HardReset ,
573+ })
574+ return
575+ }
0 commit comments