actions_test.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  1. // Copyright 2022 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package db
  5. import (
  6. "context"
  7. "os"
  8. "testing"
  9. "time"
  10. "github.com/gogs/git-module"
  11. "github.com/stretchr/testify/assert"
  12. "github.com/stretchr/testify/require"
  13. "gorm.io/gorm"
  14. "gogs.io/gogs/internal/conf"
  15. "gogs.io/gogs/internal/dbtest"
  16. )
  17. func TestIssueReferencePattern(t *testing.T) {
  18. tests := []struct {
  19. name string
  20. message string
  21. want []string
  22. }{
  23. {
  24. name: "no match",
  25. message: "Hello world!",
  26. want: nil,
  27. },
  28. {
  29. name: "contains issue numbers",
  30. message: "#123 is fixed, and #456 is WIP",
  31. want: []string{"#123", " #456"},
  32. },
  33. {
  34. name: "contains full issue references",
  35. message: "#123 is fixed, and user/repo#456 is WIP",
  36. want: []string{"#123", " user/repo#456"},
  37. },
  38. }
  39. for _, test := range tests {
  40. t.Run(test.name, func(t *testing.T) {
  41. got := issueReferencePattern.FindAllString(test.message, -1)
  42. assert.Equal(t, test.want, got)
  43. })
  44. }
  45. }
  46. func TestAction_BeforeCreate(t *testing.T) {
  47. now := time.Now()
  48. db := &gorm.DB{
  49. Config: &gorm.Config{
  50. SkipDefaultTransaction: true,
  51. NowFunc: func() time.Time {
  52. return now
  53. },
  54. },
  55. }
  56. t.Run("CreatedUnix has been set", func(t *testing.T) {
  57. action := &Action{CreatedUnix: 1}
  58. _ = action.BeforeCreate(db)
  59. assert.Equal(t, int64(1), action.CreatedUnix)
  60. })
  61. t.Run("CreatedUnix has not been set", func(t *testing.T) {
  62. action := &Action{}
  63. _ = action.BeforeCreate(db)
  64. assert.Equal(t, db.NowFunc().Unix(), action.CreatedUnix)
  65. })
  66. }
  67. func TestActions(t *testing.T) {
  68. if testing.Short() {
  69. t.Skip()
  70. }
  71. t.Parallel()
  72. tables := []interface{}{new(Action), new(User), new(Repository), new(EmailAddress), new(Watch)}
  73. db := &actions{
  74. DB: dbtest.NewDB(t, "actions", tables...),
  75. }
  76. for _, tc := range []struct {
  77. name string
  78. test func(*testing.T, *actions)
  79. }{
  80. {"CommitRepo", actionsCommitRepo},
  81. {"ListByOrganization", actionsListByOrganization},
  82. {"ListByUser", actionsListByUser},
  83. {"MergePullRequest", actionsMergePullRequest},
  84. {"MirrorSyncCreate", actionsMirrorSyncCreate},
  85. {"MirrorSyncDelete", actionsMirrorSyncDelete},
  86. {"MirrorSyncPush", actionsMirrorSyncPush},
  87. {"NewRepo", actionsNewRepo},
  88. {"PushTag", actionsPushTag},
  89. {"RenameRepo", actionsRenameRepo},
  90. {"TransferRepo", actionsTransferRepo},
  91. } {
  92. t.Run(tc.name, func(t *testing.T) {
  93. t.Cleanup(func() {
  94. err := clearTables(t, db.DB, tables...)
  95. require.NoError(t, err)
  96. })
  97. tc.test(t, db)
  98. })
  99. if t.Failed() {
  100. break
  101. }
  102. }
  103. }
  104. func actionsCommitRepo(t *testing.T, db *actions) {
  105. ctx := context.Background()
  106. alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "[email protected]", CreateUserOptions{})
  107. require.NoError(t, err)
  108. repo, err := NewReposStore(db.DB).Create(ctx,
  109. alice.ID,
  110. CreateRepoOptions{
  111. Name: "example",
  112. },
  113. )
  114. require.NoError(t, err)
  115. now := time.Unix(1588568886, 0).UTC()
  116. t.Run("new commit", func(t *testing.T) {
  117. t.Cleanup(func() {
  118. err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
  119. require.NoError(t, err)
  120. })
  121. err = db.CommitRepo(ctx,
  122. CommitRepoOptions{
  123. PusherName: alice.Name,
  124. Owner: alice,
  125. Repo: repo,
  126. RefFullName: "refs/heads/main",
  127. OldCommitID: "ca82a6dff817ec66f44342007202690a93763949",
  128. NewCommitID: "085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7",
  129. Commits: CommitsToPushCommits(
  130. []*git.Commit{
  131. {
  132. ID: git.MustIDFromString("085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7"),
  133. Author: &git.Signature{
  134. Name: "alice",
  135. Email: "[email protected]",
  136. When: now,
  137. },
  138. Committer: &git.Signature{
  139. Name: "alice",
  140. Email: "[email protected]",
  141. When: now,
  142. },
  143. Message: "A random commit",
  144. },
  145. },
  146. ),
  147. },
  148. )
  149. require.NoError(t, err)
  150. got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
  151. require.NoError(t, err)
  152. require.Len(t, got, 1)
  153. got[0].ID = 0
  154. want := []*Action{
  155. {
  156. UserID: alice.ID,
  157. OpType: ActionCommitRepo,
  158. ActUserID: alice.ID,
  159. ActUserName: alice.Name,
  160. RepoID: repo.ID,
  161. RepoUserName: alice.Name,
  162. RepoName: repo.Name,
  163. RefName: "main",
  164. IsPrivate: false,
  165. Content: `{"Len":1,"Commits":[{"Sha1":"085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7","Message":"A random commit","AuthorEmail":"[email protected]","AuthorName":"alice","CommitterEmail":"[email protected]","CommitterName":"alice","Timestamp":"2020-05-04T05:08:06Z"}],"CompareURL":"alice/example/compare/ca82a6dff817ec66f44342007202690a93763949...085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7"}`,
  166. CreatedUnix: db.NowFunc().Unix(),
  167. },
  168. }
  169. want[0].Created = time.Unix(want[0].CreatedUnix, 0)
  170. assert.Equal(t, want, got)
  171. })
  172. t.Run("new ref", func(t *testing.T) {
  173. t.Cleanup(func() {
  174. err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
  175. require.NoError(t, err)
  176. })
  177. err = db.CommitRepo(ctx,
  178. CommitRepoOptions{
  179. PusherName: alice.Name,
  180. Owner: alice,
  181. Repo: repo,
  182. RefFullName: "refs/heads/main",
  183. OldCommitID: git.EmptyID,
  184. NewCommitID: "085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7",
  185. Commits: CommitsToPushCommits(
  186. []*git.Commit{
  187. {
  188. ID: git.MustIDFromString("085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7"),
  189. Author: &git.Signature{
  190. Name: "alice",
  191. Email: "[email protected]",
  192. When: now,
  193. },
  194. Committer: &git.Signature{
  195. Name: "alice",
  196. Email: "[email protected]",
  197. When: now,
  198. },
  199. Message: "A random commit",
  200. },
  201. },
  202. ),
  203. },
  204. )
  205. require.NoError(t, err)
  206. got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
  207. require.NoError(t, err)
  208. require.Len(t, got, 2)
  209. got[0].ID = 0
  210. got[1].ID = 0
  211. want := []*Action{
  212. {
  213. UserID: alice.ID,
  214. OpType: ActionCommitRepo,
  215. ActUserID: alice.ID,
  216. ActUserName: alice.Name,
  217. RepoID: repo.ID,
  218. RepoUserName: alice.Name,
  219. RepoName: repo.Name,
  220. RefName: "main",
  221. IsPrivate: false,
  222. Content: `{"Len":1,"Commits":[{"Sha1":"085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7","Message":"A random commit","AuthorEmail":"[email protected]","AuthorName":"alice","CommitterEmail":"[email protected]","CommitterName":"alice","Timestamp":"2020-05-04T05:08:06Z"}],"CompareURL":""}`,
  223. CreatedUnix: db.NowFunc().Unix(),
  224. },
  225. {
  226. UserID: alice.ID,
  227. OpType: ActionCreateBranch,
  228. ActUserID: alice.ID,
  229. ActUserName: alice.Name,
  230. RepoID: repo.ID,
  231. RepoUserName: alice.Name,
  232. RepoName: repo.Name,
  233. RefName: "main",
  234. IsPrivate: false,
  235. Content: `{"Len":1,"Commits":[{"Sha1":"085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7","Message":"A random commit","AuthorEmail":"[email protected]","AuthorName":"alice","CommitterEmail":"[email protected]","CommitterName":"alice","Timestamp":"2020-05-04T05:08:06Z"}],"CompareURL":""}`,
  236. CreatedUnix: db.NowFunc().Unix(),
  237. },
  238. }
  239. want[0].Created = time.Unix(want[0].CreatedUnix, 0)
  240. want[1].Created = time.Unix(want[1].CreatedUnix, 0)
  241. assert.Equal(t, want, got)
  242. })
  243. t.Run("delete ref", func(t *testing.T) {
  244. t.Cleanup(func() {
  245. err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
  246. require.NoError(t, err)
  247. })
  248. err = db.CommitRepo(ctx,
  249. CommitRepoOptions{
  250. PusherName: alice.Name,
  251. Owner: alice,
  252. Repo: repo,
  253. RefFullName: "refs/heads/main",
  254. OldCommitID: "ca82a6dff817ec66f44342007202690a93763949",
  255. NewCommitID: git.EmptyID,
  256. },
  257. )
  258. require.NoError(t, err)
  259. got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
  260. require.NoError(t, err)
  261. require.Len(t, got, 1)
  262. got[0].ID = 0
  263. want := []*Action{
  264. {
  265. UserID: alice.ID,
  266. OpType: ActionDeleteBranch,
  267. ActUserID: alice.ID,
  268. ActUserName: alice.Name,
  269. RepoID: repo.ID,
  270. RepoUserName: alice.Name,
  271. RepoName: repo.Name,
  272. RefName: "main",
  273. IsPrivate: false,
  274. CreatedUnix: db.NowFunc().Unix(),
  275. },
  276. }
  277. want[0].Created = time.Unix(want[0].CreatedUnix, 0)
  278. assert.Equal(t, want, got)
  279. })
  280. }
  281. func actionsListByOrganization(t *testing.T, db *actions) {
  282. if os.Getenv("GOGS_DATABASE_TYPE") != "postgres" {
  283. t.Skip("Skipping testing with not using PostgreSQL")
  284. return
  285. }
  286. ctx := context.Background()
  287. conf.SetMockUI(t,
  288. conf.UIOpts{
  289. User: conf.UIUserOpts{
  290. NewsFeedPagingNum: 20,
  291. },
  292. },
  293. )
  294. tests := []struct {
  295. name string
  296. orgID int64
  297. actorID int64
  298. afterID int64
  299. want string
  300. }{
  301. {
  302. name: "no afterID",
  303. orgID: 1,
  304. actorID: 1,
  305. afterID: 0,
  306. want: `SELECT * FROM "action" WHERE user_id = 1 AND (true OR id < 0) AND repo_id IN (SELECT repository.id FROM "repository" JOIN team_repo ON repository.id = team_repo.repo_id WHERE team_repo.team_id IN (SELECT team_id FROM "team_user" WHERE team_user.org_id = 1 AND uid = 1) OR (repository.is_private = false AND repository.is_unlisted = false)) ORDER BY id DESC LIMIT 20`,
  307. },
  308. {
  309. name: "has afterID",
  310. orgID: 1,
  311. actorID: 1,
  312. afterID: 5,
  313. want: `SELECT * FROM "action" WHERE user_id = 1 AND (false OR id < 5) AND repo_id IN (SELECT repository.id FROM "repository" JOIN team_repo ON repository.id = team_repo.repo_id WHERE team_repo.team_id IN (SELECT team_id FROM "team_user" WHERE team_user.org_id = 1 AND uid = 1) OR (repository.is_private = false AND repository.is_unlisted = false)) ORDER BY id DESC LIMIT 20`,
  314. },
  315. }
  316. for _, test := range tests {
  317. t.Run(test.name, func(t *testing.T) {
  318. got := db.DB.ToSQL(func(tx *gorm.DB) *gorm.DB {
  319. return NewActionsStore(tx).(*actions).listByOrganization(ctx, test.orgID, test.actorID, test.afterID).Find(new(Action))
  320. })
  321. assert.Equal(t, test.want, got)
  322. })
  323. }
  324. }
  325. func actionsListByUser(t *testing.T, db *actions) {
  326. if os.Getenv("GOGS_DATABASE_TYPE") != "postgres" {
  327. t.Skip("Skipping testing with not using PostgreSQL")
  328. return
  329. }
  330. ctx := context.Background()
  331. conf.SetMockUI(t,
  332. conf.UIOpts{
  333. User: conf.UIUserOpts{
  334. NewsFeedPagingNum: 20,
  335. },
  336. },
  337. )
  338. tests := []struct {
  339. name string
  340. userID int64
  341. actorID int64
  342. afterID int64
  343. isProfile bool
  344. want string
  345. }{
  346. {
  347. name: "same user no afterID not in profile",
  348. userID: 1,
  349. actorID: 1,
  350. afterID: 0,
  351. isProfile: false,
  352. want: `SELECT * FROM "action" WHERE user_id = 1 AND (true OR id < 0) AND (true OR (is_private = false AND act_user_id = 1)) ORDER BY id DESC LIMIT 20`,
  353. },
  354. {
  355. name: "same user no afterID in profile",
  356. userID: 1,
  357. actorID: 1,
  358. afterID: 0,
  359. isProfile: true,
  360. want: `SELECT * FROM "action" WHERE user_id = 1 AND (true OR id < 0) AND (true OR (is_private = false AND act_user_id = 1)) ORDER BY id DESC LIMIT 20`,
  361. },
  362. {
  363. name: "same user has afterID not in profile",
  364. userID: 1,
  365. actorID: 1,
  366. afterID: 5,
  367. isProfile: false,
  368. want: `SELECT * FROM "action" WHERE user_id = 1 AND (false OR id < 5) AND (true OR (is_private = false AND act_user_id = 1)) ORDER BY id DESC LIMIT 20`,
  369. },
  370. {
  371. name: "different user no afterID in profile",
  372. userID: 1,
  373. actorID: 2,
  374. afterID: 0,
  375. isProfile: true,
  376. want: `SELECT * FROM "action" WHERE user_id = 1 AND (true OR id < 0) AND (false OR (is_private = false AND act_user_id = 1)) ORDER BY id DESC LIMIT 20`,
  377. },
  378. }
  379. for _, test := range tests {
  380. t.Run(test.name, func(t *testing.T) {
  381. got := db.DB.ToSQL(func(tx *gorm.DB) *gorm.DB {
  382. return NewActionsStore(tx).(*actions).listByUser(ctx, test.userID, test.actorID, test.afterID, test.isProfile).Find(new(Action))
  383. })
  384. assert.Equal(t, test.want, got)
  385. })
  386. }
  387. }
  388. func actionsMergePullRequest(t *testing.T, db *actions) {
  389. ctx := context.Background()
  390. alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "[email protected]", CreateUserOptions{})
  391. require.NoError(t, err)
  392. repo, err := NewReposStore(db.DB).Create(ctx,
  393. alice.ID,
  394. CreateRepoOptions{
  395. Name: "example",
  396. },
  397. )
  398. require.NoError(t, err)
  399. err = db.MergePullRequest(ctx,
  400. alice,
  401. alice,
  402. repo,
  403. &Issue{
  404. Index: 1,
  405. Title: "Fix issue 1",
  406. },
  407. )
  408. require.NoError(t, err)
  409. got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
  410. require.NoError(t, err)
  411. require.Len(t, got, 1)
  412. got[0].ID = 0
  413. want := []*Action{
  414. {
  415. UserID: alice.ID,
  416. OpType: ActionMergePullRequest,
  417. ActUserID: alice.ID,
  418. ActUserName: alice.Name,
  419. RepoID: repo.ID,
  420. RepoUserName: alice.Name,
  421. RepoName: repo.Name,
  422. IsPrivate: false,
  423. Content: `1|Fix issue 1`,
  424. CreatedUnix: db.NowFunc().Unix(),
  425. },
  426. }
  427. want[0].Created = time.Unix(want[0].CreatedUnix, 0)
  428. assert.Equal(t, want, got)
  429. }
  430. func actionsMirrorSyncCreate(t *testing.T, db *actions) {
  431. ctx := context.Background()
  432. alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "[email protected]", CreateUserOptions{})
  433. require.NoError(t, err)
  434. repo, err := NewReposStore(db.DB).Create(ctx,
  435. alice.ID,
  436. CreateRepoOptions{
  437. Name: "example",
  438. },
  439. )
  440. require.NoError(t, err)
  441. err = db.MirrorSyncCreate(ctx,
  442. alice,
  443. repo,
  444. "main",
  445. )
  446. require.NoError(t, err)
  447. got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
  448. require.NoError(t, err)
  449. require.Len(t, got, 1)
  450. got[0].ID = 0
  451. want := []*Action{
  452. {
  453. UserID: alice.ID,
  454. OpType: ActionMirrorSyncCreate,
  455. ActUserID: alice.ID,
  456. ActUserName: alice.Name,
  457. RepoID: repo.ID,
  458. RepoUserName: alice.Name,
  459. RepoName: repo.Name,
  460. RefName: "main",
  461. IsPrivate: false,
  462. CreatedUnix: db.NowFunc().Unix(),
  463. },
  464. }
  465. want[0].Created = time.Unix(want[0].CreatedUnix, 0)
  466. assert.Equal(t, want, got)
  467. }
  468. func actionsMirrorSyncDelete(t *testing.T, db *actions) {
  469. ctx := context.Background()
  470. alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "[email protected]", CreateUserOptions{})
  471. require.NoError(t, err)
  472. repo, err := NewReposStore(db.DB).Create(ctx,
  473. alice.ID,
  474. CreateRepoOptions{
  475. Name: "example",
  476. },
  477. )
  478. require.NoError(t, err)
  479. err = db.MirrorSyncDelete(ctx,
  480. alice,
  481. repo,
  482. "main",
  483. )
  484. require.NoError(t, err)
  485. got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
  486. require.NoError(t, err)
  487. require.Len(t, got, 1)
  488. got[0].ID = 0
  489. want := []*Action{
  490. {
  491. UserID: alice.ID,
  492. OpType: ActionMirrorSyncDelete,
  493. ActUserID: alice.ID,
  494. ActUserName: alice.Name,
  495. RepoID: repo.ID,
  496. RepoUserName: alice.Name,
  497. RepoName: repo.Name,
  498. RefName: "main",
  499. IsPrivate: false,
  500. CreatedUnix: db.NowFunc().Unix(),
  501. },
  502. }
  503. want[0].Created = time.Unix(want[0].CreatedUnix, 0)
  504. assert.Equal(t, want, got)
  505. }
  506. func actionsMirrorSyncPush(t *testing.T, db *actions) {
  507. ctx := context.Background()
  508. alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "[email protected]", CreateUserOptions{})
  509. require.NoError(t, err)
  510. repo, err := NewReposStore(db.DB).Create(ctx,
  511. alice.ID,
  512. CreateRepoOptions{
  513. Name: "example",
  514. },
  515. )
  516. require.NoError(t, err)
  517. now := time.Unix(1588568886, 0).UTC()
  518. err = db.MirrorSyncPush(ctx,
  519. MirrorSyncPushOptions{
  520. Owner: alice,
  521. Repo: repo,
  522. RefName: "main",
  523. OldCommitID: "ca82a6dff817ec66f44342007202690a93763949",
  524. NewCommitID: "085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7",
  525. Commits: CommitsToPushCommits(
  526. []*git.Commit{
  527. {
  528. ID: git.MustIDFromString("085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7"),
  529. Author: &git.Signature{
  530. Name: "alice",
  531. Email: "[email protected]",
  532. When: now,
  533. },
  534. Committer: &git.Signature{
  535. Name: "alice",
  536. Email: "[email protected]",
  537. When: now,
  538. },
  539. Message: "A random commit",
  540. },
  541. },
  542. ),
  543. },
  544. )
  545. require.NoError(t, err)
  546. got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
  547. require.NoError(t, err)
  548. require.Len(t, got, 1)
  549. got[0].ID = 0
  550. want := []*Action{
  551. {
  552. UserID: alice.ID,
  553. OpType: ActionMirrorSyncPush,
  554. ActUserID: alice.ID,
  555. ActUserName: alice.Name,
  556. RepoID: repo.ID,
  557. RepoUserName: alice.Name,
  558. RepoName: repo.Name,
  559. RefName: "main",
  560. IsPrivate: false,
  561. Content: `{"Len":1,"Commits":[{"Sha1":"085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7","Message":"A random commit","AuthorEmail":"[email protected]","AuthorName":"alice","CommitterEmail":"[email protected]","CommitterName":"alice","Timestamp":"2020-05-04T05:08:06Z"}],"CompareURL":"alice/example/compare/ca82a6dff817ec66f44342007202690a93763949...085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7"}`,
  562. CreatedUnix: db.NowFunc().Unix(),
  563. },
  564. }
  565. want[0].Created = time.Unix(want[0].CreatedUnix, 0)
  566. assert.Equal(t, want, got)
  567. }
  568. func actionsNewRepo(t *testing.T, db *actions) {
  569. ctx := context.Background()
  570. alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "[email protected]", CreateUserOptions{})
  571. require.NoError(t, err)
  572. repo, err := NewReposStore(db.DB).Create(ctx,
  573. alice.ID,
  574. CreateRepoOptions{
  575. Name: "example",
  576. },
  577. )
  578. require.NoError(t, err)
  579. t.Run("new repo", func(t *testing.T) {
  580. t.Cleanup(func() {
  581. err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
  582. require.NoError(t, err)
  583. })
  584. err = db.NewRepo(ctx, alice, alice, repo)
  585. require.NoError(t, err)
  586. got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
  587. require.NoError(t, err)
  588. require.Len(t, got, 1)
  589. got[0].ID = 0
  590. want := []*Action{
  591. {
  592. UserID: alice.ID,
  593. OpType: ActionCreateRepo,
  594. ActUserID: alice.ID,
  595. ActUserName: alice.Name,
  596. RepoID: repo.ID,
  597. RepoUserName: alice.Name,
  598. RepoName: repo.Name,
  599. IsPrivate: false,
  600. CreatedUnix: db.NowFunc().Unix(),
  601. },
  602. }
  603. want[0].Created = time.Unix(want[0].CreatedUnix, 0)
  604. assert.Equal(t, want, got)
  605. })
  606. t.Run("fork repo", func(t *testing.T) {
  607. t.Cleanup(func() {
  608. err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
  609. require.NoError(t, err)
  610. })
  611. repo.IsFork = true
  612. err = db.NewRepo(ctx, alice, alice, repo)
  613. require.NoError(t, err)
  614. got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
  615. require.NoError(t, err)
  616. require.Len(t, got, 1)
  617. got[0].ID = 0
  618. want := []*Action{
  619. {
  620. UserID: alice.ID,
  621. OpType: ActionForkRepo,
  622. ActUserID: alice.ID,
  623. ActUserName: alice.Name,
  624. RepoID: repo.ID,
  625. RepoUserName: alice.Name,
  626. RepoName: repo.Name,
  627. IsPrivate: false,
  628. CreatedUnix: db.NowFunc().Unix(),
  629. },
  630. }
  631. want[0].Created = time.Unix(want[0].CreatedUnix, 0)
  632. assert.Equal(t, want, got)
  633. })
  634. }
  635. func actionsPushTag(t *testing.T, db *actions) {
  636. ctx := context.Background()
  637. alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "[email protected]", CreateUserOptions{})
  638. require.NoError(t, err)
  639. repo, err := NewReposStore(db.DB).Create(ctx,
  640. alice.ID,
  641. CreateRepoOptions{
  642. Name: "example",
  643. },
  644. )
  645. require.NoError(t, err)
  646. t.Run("new tag", func(t *testing.T) {
  647. t.Cleanup(func() {
  648. err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
  649. require.NoError(t, err)
  650. })
  651. err = db.PushTag(ctx,
  652. PushTagOptions{
  653. Owner: alice,
  654. Repo: repo,
  655. PusherName: alice.Name,
  656. RefFullName: "refs/tags/v1.0.0",
  657. NewCommitID: "085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7",
  658. },
  659. )
  660. require.NoError(t, err)
  661. got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
  662. require.NoError(t, err)
  663. require.Len(t, got, 1)
  664. got[0].ID = 0
  665. want := []*Action{
  666. {
  667. UserID: alice.ID,
  668. OpType: ActionPushTag,
  669. ActUserID: alice.ID,
  670. ActUserName: alice.Name,
  671. RepoID: repo.ID,
  672. RepoUserName: alice.Name,
  673. RepoName: repo.Name,
  674. RefName: "v1.0.0",
  675. IsPrivate: false,
  676. CreatedUnix: db.NowFunc().Unix(),
  677. },
  678. }
  679. want[0].Created = time.Unix(want[0].CreatedUnix, 0)
  680. assert.Equal(t, want, got)
  681. })
  682. t.Run("delete tag", func(t *testing.T) {
  683. t.Cleanup(func() {
  684. err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
  685. require.NoError(t, err)
  686. })
  687. err = db.PushTag(ctx,
  688. PushTagOptions{
  689. Owner: alice,
  690. Repo: repo,
  691. PusherName: alice.Name,
  692. RefFullName: "refs/tags/v1.0.0",
  693. NewCommitID: git.EmptyID,
  694. },
  695. )
  696. require.NoError(t, err)
  697. got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
  698. require.NoError(t, err)
  699. require.Len(t, got, 1)
  700. got[0].ID = 0
  701. want := []*Action{
  702. {
  703. UserID: alice.ID,
  704. OpType: ActionDeleteTag,
  705. ActUserID: alice.ID,
  706. ActUserName: alice.Name,
  707. RepoID: repo.ID,
  708. RepoUserName: alice.Name,
  709. RepoName: repo.Name,
  710. RefName: "v1.0.0",
  711. IsPrivate: false,
  712. CreatedUnix: db.NowFunc().Unix(),
  713. },
  714. }
  715. want[0].Created = time.Unix(want[0].CreatedUnix, 0)
  716. assert.Equal(t, want, got)
  717. })
  718. }
  719. func actionsRenameRepo(t *testing.T, db *actions) {
  720. ctx := context.Background()
  721. alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "[email protected]", CreateUserOptions{})
  722. require.NoError(t, err)
  723. repo, err := NewReposStore(db.DB).Create(ctx,
  724. alice.ID,
  725. CreateRepoOptions{
  726. Name: "example",
  727. },
  728. )
  729. require.NoError(t, err)
  730. err = db.RenameRepo(ctx, alice, alice, "oldExample", repo)
  731. require.NoError(t, err)
  732. got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
  733. require.NoError(t, err)
  734. require.Len(t, got, 1)
  735. got[0].ID = 0
  736. want := []*Action{
  737. {
  738. UserID: alice.ID,
  739. OpType: ActionRenameRepo,
  740. ActUserID: alice.ID,
  741. ActUserName: alice.Name,
  742. RepoID: repo.ID,
  743. RepoUserName: alice.Name,
  744. RepoName: repo.Name,
  745. IsPrivate: false,
  746. Content: "oldExample",
  747. CreatedUnix: db.NowFunc().Unix(),
  748. },
  749. }
  750. want[0].Created = time.Unix(want[0].CreatedUnix, 0)
  751. assert.Equal(t, want, got)
  752. }
  753. func actionsTransferRepo(t *testing.T, db *actions) {
  754. ctx := context.Background()
  755. alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "[email protected]", CreateUserOptions{})
  756. require.NoError(t, err)
  757. bob, err := NewUsersStore(db.DB).Create(ctx, "bob", "[email protected]", CreateUserOptions{})
  758. require.NoError(t, err)
  759. repo, err := NewReposStore(db.DB).Create(ctx,
  760. alice.ID,
  761. CreateRepoOptions{
  762. Name: "example",
  763. },
  764. )
  765. require.NoError(t, err)
  766. err = db.TransferRepo(ctx, alice, alice, bob, repo)
  767. require.NoError(t, err)
  768. got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
  769. require.NoError(t, err)
  770. require.Len(t, got, 1)
  771. got[0].ID = 0
  772. want := []*Action{
  773. {
  774. UserID: alice.ID,
  775. OpType: ActionTransferRepo,
  776. ActUserID: alice.ID,
  777. ActUserName: alice.Name,
  778. RepoID: repo.ID,
  779. RepoUserName: bob.Name,
  780. RepoName: repo.Name,
  781. IsPrivate: false,
  782. Content: "alice/example",
  783. CreatedUnix: db.NowFunc().Unix(),
  784. },
  785. }
  786. want[0].Created = time.Unix(want[0].CreatedUnix, 0)
  787. assert.Equal(t, want, got)
  788. }