diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index cee094a..9db8508 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -10,10 +10,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7.0.1 - name: Setup asdf - uses: asdf-vm/actions/setup@9cd779f40fe38688dd19505ccbc4eaaf018b44e7 + uses: asdf-vm/actions/setup@v4.0.1 with: asdf_version: 0.16.7 diff --git a/.github/workflows/realm-tests.yml b/.github/workflows/realm-tests.yml index 513ac69..b7610ee 100644 --- a/.github/workflows/realm-tests.yml +++ b/.github/workflows/realm-tests.yml @@ -7,29 +7,73 @@ on: branches: [main] jobs: + realm-unit-tests: + runs-on: ubuntu-latest + + steps: + - name: Checkout dsocial + uses: actions/checkout@v7.0.1 + + - name: Set up Go + uses: actions/setup-go@v7.0.0 + with: + go-version: "1.25.9" + + - name: Checkout gnolang/gno + uses: actions/checkout@v7.0.1 + with: + repository: gnolang/gno + ref: 14fe3eb356c52dd325c9cc10fc77d248b3b88f32 + path: .gno + + - name: Cache Go build + uses: actions/cache@v6.1.0 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-gno-${{ hashFiles('.gno/go.sum', '.gno/contribs/gnodev/go.sum') }} + restore-keys: ${{ runner.os }}-go-gno- + + - name: Install gno + working-directory: .gno + run: go install ./gnovm/cmd/gno + + # Resolve imports from the pinned Gno examples workspace. + - name: Prepare realm unit tests + run: | + mkdir -p .gno/examples/gno.land/r/berty + cp -R realm .gno/examples/gno.land/r/berty/social + + - name: Run realm unit tests + working-directory: .gno/examples + env: + GNOROOT: ${{ github.workspace }}/.gno + run: gno test -v ./gno.land/r/berty/social + realm-tests: runs-on: ubuntu-latest steps: - name: Checkout dsocial - uses: actions/checkout@v4 + uses: actions/checkout@v7.0.1 - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v7.0.0 with: - go-version: "1.24" + go-version: "1.25.9" - name: Checkout gnolang/gno - uses: actions/checkout@v4 + uses: actions/checkout@v7.0.1 with: repository: gnolang/gno # Pin to the gno version this realm was developed against. # Update this ref when bumping gno compatibility. - ref: d8a351e7509ce945267b0d929ead44b981b4061b + ref: 14fe3eb356c52dd325c9cc10fc77d248b3b88f32 path: .gno - name: Cache Go build - uses: actions/cache@v4 + uses: actions/cache@v6.1.0 with: path: | ~/.cache/go-build diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ae85895..365ab9d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,10 +8,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7.0.1 - name: Setup asdf - uses: asdf-vm/actions/setup@9cd779f40fe38688dd19505ccbc4eaaf018b44e7 + uses: asdf-vm/actions/setup@v4.0.1 with: asdf_version: 0.16.7 @@ -27,7 +27,7 @@ jobs: asdf set -u nodejs ${{ env.node_version }} - name: Setup Expo and EAS - uses: expo/expo-github-action@v8 + uses: expo/expo-github-action@9.0.1 with: eas-version: latest token: ${{ secrets.EXPO_TOKEN }} @@ -37,7 +37,7 @@ jobs: run: npm ci - name: Semantic Release - uses: cycjimmy/semantic-release-action@v4 + uses: cycjimmy/semantic-release-action@v8.1.4 id: semantic with: working_directory: ./mobile diff --git a/realm/post.gno b/realm/post.gno index 65c9916..eeb1b2e 100644 --- a/realm/post.gno +++ b/realm/post.gno @@ -5,7 +5,7 @@ import ( "strconv" "time" - "gno.land/p/moul/txlink" + "gno.land/p/moul/txlink/v0" "gno.land/p/nt/bptree/v0" "gno.land/p/nt/ufmt/v0" ) @@ -103,8 +103,8 @@ func (post *Post) AddRepostTo(creator address, comment string, dst *UserPosts) * func (post *Post) GetReply(pid PostID) *Post { pidkey := postIDKey(pid) - replyI, ok := post.repliesAll.Get(pidkey) - if !ok { + replyI := post.repliesAll.Get(pidkey) + if replyI == nil { return nil } else { return replyI.(*Post) @@ -151,8 +151,8 @@ func (post *Post) RemoveReaction(userAddr address, reaction Reaction) bool { // Return the count of reactions for the reaction. func (post *Post) GetReactionCount(reaction Reaction) int { key := reactionKey(reaction) - valueI, exists := post.reactions.Get(key) - if exists { + valueI := post.reactions.Get(key) + if valueI != nil { return valueI.(*bptree.BPTree).Size() } else { return 0 diff --git a/realm/social_test.gno b/realm/social_test.gno new file mode 100644 index 0000000..4b6fec9 --- /dev/null +++ b/realm/social_test.gno @@ -0,0 +1,48 @@ +package social + +import "testing" + +func TestPostLookups(t *testing.T) { + addr := address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + if getUserPosts(addr) != nil { + t.Fatal("unexpected posts for an unknown user") + } + userPosts := getOrCreateUserPosts(addr, "alice") + if getUserPosts(addr) != userPosts { + t.Fatal("stored user posts were not found") + } + if userPosts.GetThread(1) != nil { + t.Fatal("unexpected thread in an empty user feed") + } + thread := userPosts.AddThread("Hello") + if userPosts.GetThread(thread.id) != thread { + t.Fatal("stored thread was not found") + } + if thread.GetReply(thread.id+1) != nil { + t.Fatal("unexpected reply in an empty thread") + } + reply := thread.AddReply(addr, "Reply") + if thread.GetReply(reply.id) != reply { + t.Fatal("stored reply was not found") + } +} + +func TestReactionLookups(t *testing.T) { + userPosts := newUserPosts("/r/berty/social:alice", address("alice")) + thread := userPosts.AddThread("Hello") + if thread.GetReactionCount(Gnod) != 0 { + t.Fatal("unexpected reactions on a new post") + } + if !thread.AddReaction(address("bob"), Gnod) { + t.Fatal("first reaction was not added") + } + if thread.AddReaction(address("bob"), Gnod) { + t.Fatal("duplicate reaction was added") + } + if thread.GetReactionCount(Gnod) != 1 { + t.Fatal("stored reaction was not counted") + } + if !thread.RemoveReaction(address("bob"), Gnod) || thread.GetReactionCount(Gnod) != 0 { + t.Fatal("reaction was not removed") + } +} diff --git a/realm/userposts.gno b/realm/userposts.gno index 4e502c1..204c973 100644 --- a/realm/userposts.gno +++ b/realm/userposts.gno @@ -7,7 +7,7 @@ import ( "strings" "time" - "gno.land/p/moul/txlink" + "gno.land/p/moul/txlink/v0" "gno.land/p/nt/bptree/v0" "gno.land/p/nt/ufmt/v0" "gno.land/r/sys/users" @@ -50,8 +50,8 @@ func newUserPosts(url string, userAddr address) *UserPosts { func (userPosts *UserPosts) GetThread(pid PostID) *Post { pidkey := postIDKey(pid) - postI, exists := userPosts.threads.Get(pidkey) - if !exists { + postI := userPosts.threads.Get(pidkey) + if postI == nil { return nil } return postI.(*Post) diff --git a/realm/util.gno b/realm/util.gno index cede851..1307bcf 100644 --- a/realm/util.gno +++ b/realm/util.gno @@ -14,8 +14,8 @@ import ( // Get the UserPosts for the user. func getUserPosts(userAddr address) *UserPosts { - userPosts, exists := gUserPostsByAddress.Get(userAddr.String()) - if !exists { + userPosts := gUserPostsByAddress.Get(userAddr.String()) + if userPosts == nil { return nil } @@ -67,8 +67,8 @@ func reactionKey(reaction Reaction) string { // Otherwise, add the reaction key to reactions, set the value to an empty bptree.BPTree and return it. func getOrCreateReactionValue(reactions *bptree.BPTree, reaction Reaction) *bptree.BPTree { key := reactionKey(reaction) - valueI, exists := reactions.Get(key) - if exists { + valueI := reactions.Get(key) + if valueI != nil { return valueI.(*bptree.BPTree) } else { value := bptree.NewBPTree32()