Skip to content

Commit

Permalink
Merge pull request #2778 from onflow/bastian/capability-exists
Browse files Browse the repository at this point in the history
  • Loading branch information
turbolent authored Sep 13, 2023
2 parents 9367893 + 4dd9ef3 commit 238db58
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 25 deletions.
76 changes: 62 additions & 14 deletions runtime/capabilities_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,16 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {
let rAsSCap = self.account.capabilities.storage.issue<&S>(/storage/r)
self.account.capabilities.publish(rAsSCap, at: /public/rAsS)
let noCap = self.account.capabilities.storage.issue<&R>(/storage/nonExistent)
self.account.capabilities.publish(noCap, at: /public/nonExistent)
let noCap = self.account.capabilities.storage.issue<&R>(/storage/nonExistentTarget)
self.account.capabilities.publish(noCap, at: /public/nonExistentTarget)
}
access(all)
fun testR() {
let cap = self.account.capabilities.get<&R>(/public/r)!
let path = /public/r
let cap = self.account.capabilities.get<&R>(path)!
assert(self.account.capabilities.exists(path))
assert(
cap.check(),
Expand All @@ -156,7 +159,10 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {
access(all)
fun testRAsR2() {
let cap = self.account.capabilities.get<&R2>(/public/rAsR2)!
let path = /public/rAsR2
let cap = self.account.capabilities.get<&R2>(path)!
assert(self.account.capabilities.exists(path))
assert(
!cap.check(),
Expand All @@ -176,7 +182,10 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {
access(all)
fun testRAsS() {
let cap = self.account.capabilities.get<&S>(/public/rAsS)!
let path = /public/rAsS
let cap = self.account.capabilities.get<&S>(path)!
assert(self.account.capabilities.exists(path))
assert(
!cap.check(),
Expand All @@ -195,8 +204,11 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {
}
access(all)
fun testNonExistent() {
let cap = self.account.capabilities.get<&R>(/public/nonExistent)!
fun testNonExistentTarget() {
let path = /public/nonExistentTarget
let cap = self.account.capabilities.get<&R>(path)!
assert(self.account.capabilities.exists(path))
assert(
!cap.check(),
Expand All @@ -214,6 +226,13 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {
)
}
access(all)
fun testNonExistent() {
let path = /public/nonExistent
assert(self.account.capabilities.get<&AnyResource>(path) == nil)
assert(!self.account.capabilities.exists(path))
}
access(all)
fun testSwap(): Int {
let ref = self.account.capabilities.get<&R>(/public/r)!.borrow()!
Expand Down Expand Up @@ -274,6 +293,11 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {
require.NoError(t, err)
})

t.Run("testNonExistentTarget", func(t *testing.T) {
_, err := invoke("testNonExistentTarget")
require.NoError(t, err)
})

t.Run("testNonExistent", func(t *testing.T) {
_, err := invoke("testNonExistent")
require.NoError(t, err)
Expand Down Expand Up @@ -352,13 +376,16 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {
let sAsRCap = self.account.capabilities.storage.issue<&R>(/storage/s)
self.account.capabilities.publish(sAsRCap, at: /public/sAsR)
let noCap = self.account.capabilities.storage.issue<&S>(/storage/nonExistent)
self.account.capabilities.publish(noCap, at: /public/nonExistent)
let noCap = self.account.capabilities.storage.issue<&S>(/storage/nonExistentTarget)
self.account.capabilities.publish(noCap, at: /public/nonExistentTarget)
}
access(all)
fun testS() {
let cap = self.account.capabilities.get<&S>(/public/s)!
let path = /public/s
let cap = self.account.capabilities.get<&S>(path)!
assert(self.account.capabilities.exists(path))
assert(
cap.check(),
Expand All @@ -384,7 +411,10 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {
access(all)
fun testSAsS2() {
let cap = self.account.capabilities.get<&S2>(/public/sAsS2)!
let path = /public/sAsS2
let cap = self.account.capabilities.get<&S2>(path)!
assert(self.account.capabilities.exists(path))
assert(
!cap.check(),
Expand All @@ -404,7 +434,10 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {
access(all)
fun testSAsR() {
let cap = self.account.capabilities.get<&R>(/public/sAsR)!
let path = /public/sAsR
let cap = self.account.capabilities.get<&R>(path)!
assert(self.account.capabilities.exists(path))
assert(
!cap.check(),
Expand All @@ -423,8 +456,11 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {
}
access(all)
fun testNonExistent() {
let cap = self.account.capabilities.get<&S>(/public/nonExistent)!
fun testNonExistentTarget() {
let path = /public/nonExistentTarget
let cap = self.account.capabilities.get<&S>(path)!
assert(self.account.capabilities.exists(path))
assert(
!cap.check(),
Expand All @@ -442,6 +478,13 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {
)
}
access(all)
fun testNonExistent() {
let path = /public/nonExistent
assert(self.account.capabilities.get<&AnyStruct>(path) == nil)
assert(!self.account.capabilities.exists(path))
}
access(all)
fun testSwap(): Int {
let ref = self.account.capabilities.get<&S>(/public/s)!.borrow()!
Expand Down Expand Up @@ -501,6 +544,11 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {
require.NoError(t, err)
})

t.Run("testNonExistentTarget", func(t *testing.T) {
_, err := invoke("testNonExistentTarget")
require.NoError(t, err)
})

t.Run("testNonExistent", func(t *testing.T) {
_, err := invoke("testNonExistent")
require.NoError(t, err)
Expand Down
35 changes: 24 additions & 11 deletions runtime/capabilitycontrollers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,14 @@ func TestRuntimeCapabilityControllers(t *testing.T) {
`
transaction {
prepare(signer: auth(Capabilities) &Account) {
let path = /public/x
// Act
let gotCap: Capability<&AnyStruct>? =
%s.capabilities.get<&AnyStruct>(/public/x)
%[1]s.capabilities.get<&AnyStruct>(path)
// Assert
assert(!%[1]s.capabilities.exists(path))
assert(gotCap == nil)
}
}
Expand Down Expand Up @@ -244,9 +247,10 @@ func TestRuntimeCapabilityControllers(t *testing.T) {
// Act
let gotCap: Capability<&Test.R> =
%s.capabilities.get<&Test.R>(publicPath)!
%[1]s.capabilities.get<&Test.R>(publicPath)!
// Assert
assert(%[1]s.capabilities.exists(publicPath))
assert(issuedCap.id == expectedCapID)
assert(gotCap.check())
assert(gotCap.id == expectedCapID)
Expand Down Expand Up @@ -276,9 +280,10 @@ func TestRuntimeCapabilityControllers(t *testing.T) {
// Act
let gotCap: Capability<&Account> =
%s.capabilities.get<&Account>(publicPath)!
%[1]s.capabilities.get<&Account>(publicPath)!
// Assert
assert(%[1]s.capabilities.exists(publicPath))
assert(issuedCap.id == expectedCapID)
assert(gotCap.check())
assert(gotCap.id == expectedCapID)
Expand Down Expand Up @@ -319,10 +324,11 @@ func TestRuntimeCapabilityControllers(t *testing.T) {
// Act
let gotCap: Capability<&Test.R> =
%s.capabilities.get<&Test.R>(publicPath)!
%[1]s.capabilities.get<&Test.R>(publicPath)!
let ref: &Test.R = gotCap.borrow()!
// Assert
assert(%[1]s.capabilities.exists(publicPath))
assert(issuedCap.id == expectedCapID)
assert(gotCap.check())
assert(gotCap.id == expectedCapID)
Expand Down Expand Up @@ -354,10 +360,11 @@ func TestRuntimeCapabilityControllers(t *testing.T) {
// Act
let gotCap: Capability<&Account> =
%s.capabilities.get<&Account>(publicPath)!
%[1]s.capabilities.get<&Account>(publicPath)!
let ref: &Account = gotCap.borrow()!
// Assert
assert(%[1]s.capabilities.exists(publicPath))
assert(issuedCap.id == expectedCapID)
assert(gotCap.check())
assert(gotCap.id == expectedCapID)
Expand Down Expand Up @@ -399,9 +406,10 @@ func TestRuntimeCapabilityControllers(t *testing.T) {
// Act
let gotCap: Capability<auth(Test.X) &Test.R>? =
%s.capabilities.get<auth(Test.X) &Test.R>(publicPath)
%[1]s.capabilities.get<auth(Test.X) &Test.R>(publicPath)
// Assert
assert(%[1]s.capabilities.exists(publicPath))
assert(issuedCap.id == expectedCapID)
assert(gotCap == nil)
}
Expand Down Expand Up @@ -433,9 +441,10 @@ func TestRuntimeCapabilityControllers(t *testing.T) {
// Act
let gotCap: Capability<&Test.R>? =
%s.capabilities.get<&Test.R>(publicPath)
%[1]s.capabilities.get<&Test.R>(publicPath)
// Assert
assert(%[1]s.capabilities.exists(publicPath))
assert(issuedCap.id == expectedCapID)
assert(gotCap == nil)
}
Expand Down Expand Up @@ -475,9 +484,10 @@ func TestRuntimeCapabilityControllers(t *testing.T) {
// Act
let gotCap: Capability<&Test.S>? =
%s.capabilities.get<&Test.S>(publicPath)
%[1]s.capabilities.get<&Test.S>(publicPath)
// Assert
assert(%[1]s.capabilities.exists(publicPath))
assert(issuedCap.id == expectedCapID)
assert(gotCap == nil)
}
Expand Down Expand Up @@ -507,9 +517,10 @@ func TestRuntimeCapabilityControllers(t *testing.T) {
// Act
let gotCap: Capability<&AnyResource>? =
%s.capabilities.get<&AnyResource>(publicPath)
%[1]s.capabilities.get<&AnyResource>(publicPath)
// Assert
assert(%[1]s.capabilities.exists(publicPath))
assert(issuedCap.id == expectedCapID)
assert(gotCap == nil)
}
Expand Down Expand Up @@ -549,9 +560,10 @@ func TestRuntimeCapabilityControllers(t *testing.T) {
// Act
let gotCap: Capability<&Test.R>? =
%s.capabilities.get<&Test.R>(publicPath)
%[1]s.capabilities.get<&Test.R>(publicPath)
// Assert
assert(!%[1]s.capabilities.exists(publicPath))
assert(issuedCap.id == expectedCapID)
assert(unpublishedcap!.id == expectedCapID)
assert(gotCap == nil)
Expand Down Expand Up @@ -582,9 +594,10 @@ func TestRuntimeCapabilityControllers(t *testing.T) {
// Act
let gotCap: Capability<&Account>? =
%s.capabilities.get<&Account>(publicPath)
%[1]s.capabilities.get<&Account>(publicPath)
// Assert
assert(!%[1]s.capabilities.exists(publicPath))
assert(issuedCap.id == expectedCapID)
assert(unpublishedcap!.id == expectedCapID)
assert(gotCap == nil)
Expand Down
2 changes: 2 additions & 0 deletions runtime/interpreter/value_account_capabilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func NewAccountCapabilitiesValue(
address AddressValue,
getFunction FunctionValue,
borrowFunction FunctionValue,
existsFunction FunctionValue,
publishFunction FunctionValue,
unpublishFunction FunctionValue,
storageCapabilitiesConstructor func() Value,
Expand All @@ -44,6 +45,7 @@ func NewAccountCapabilitiesValue(
fields := map[string]Value{
sema.Account_CapabilitiesTypeGetFunctionName: getFunction,
sema.Account_CapabilitiesTypeBorrowFunctionName: borrowFunction,
sema.Account_CapabilitiesTypeExistsFunctionName: existsFunction,
sema.Account_CapabilitiesTypePublishFunctionName: publishFunction,
sema.Account_CapabilitiesTypeUnpublishFunctionName: unpublishFunction,
}
Expand Down
4 changes: 4 additions & 0 deletions runtime/sema/account.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,10 @@ struct Account {
access(all)
view fun borrow<T: &Any>(_ path: PublicPath): T?

/// Returns true if a capability exists at the given public path.
access(all)
view fun exists(_ path: PublicPath): Bool

/// Publish the capability at the given public path.
///
/// If there is already a capability published under the given path, the program aborts.
Expand Down
27 changes: 27 additions & 0 deletions runtime/sema/account.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 238db58

Please sign in to comment.