1
0

actions_test.go 23 KB

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