本文整理汇总了Golang中github.com/snapcore/snapd/snap/snaptest.MockInfo函数的典型用法代码示例。如果您正苦于以下问题:Golang MockInfo函数的具体用法?Golang MockInfo怎么用?Golang MockInfo使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了MockInfo函数的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的Golang代码示例。
示例1: SetUpTest
func (s *DisconnectSnapSuite) SetUpTest(c *C) {
s.repo = NewRepository()
err := s.repo.AddInterface(&TestInterface{InterfaceName: "iface-a"})
c.Assert(err, IsNil)
err = s.repo.AddInterface(&TestInterface{InterfaceName: "iface-b"})
c.Assert(err, IsNil)
s.s1 = snaptest.MockInfo(c, `
name: s1
plugs:
iface-a:
slots:
iface-b:
`, nil)
err = s.repo.AddSnap(s.s1)
c.Assert(err, IsNil)
s.s2 = snaptest.MockInfo(c, `
name: s2
plugs:
iface-b:
slots:
iface-a:
`, nil)
c.Assert(err, IsNil)
err = s.repo.AddSnap(s.s2)
c.Assert(err, IsNil)
}
开发者ID:clobrano,项目名称:snappy,代码行数:29,代码来源:repo_test.go
示例2: makeContentConnectionTestSnaps
// internal helper that creates a new repository with two snaps, one
// is a content plug and one a content slot
func makeContentConnectionTestSnaps(c *C, plugContentToken, slotContentToken string) (*Repository, *snap.Info, *snap.Info) {
repo := NewRepository()
err := repo.AddInterface(&TestInterface{InterfaceName: "content", AutoConnectFlag: true})
plugSnap := snaptest.MockInfo(c, fmt.Sprintf(`
name: content-plug-snap
plugs:
import-content:
interface: content
content: %s
`, plugContentToken), nil)
slotSnap := snaptest.MockInfo(c, fmt.Sprintf(`
name: content-slot-snap
slots:
exported-content:
interface: content
content: %s
`, slotContentToken), nil)
err = repo.AddSnap(plugSnap)
c.Assert(err, IsNil)
err = repo.AddSnap(slotSnap)
c.Assert(err, IsNil)
return repo, plugSnap, slotSnap
}
开发者ID:clobrano,项目名称:snappy,代码行数:28,代码来源:repo_test.go
示例3: TestConnectionMismatchName
func (s *DbusInterfaceSuite) TestConnectionMismatchName(c *C) {
const plugYaml = `name: plugger
version: 1.0
plugs:
this:
interface: dbus
bus: session
name: org.slotter.session
`
const slotYaml = `name: slotter
version: 1.0
slots:
this:
interface: dbus
bus: session
name: org.slotter.nomatch
`
plugInfo := snaptest.MockInfo(c, plugYaml, nil)
plug := &interfaces.Plug{PlugInfo: plugInfo.Plugs["this"]}
slotInfo := snaptest.MockInfo(c, slotYaml, nil)
slot := &interfaces.Slot{SlotInfo: slotInfo.Slots["this"]}
snippet, err := s.iface.ConnectedPlugSnippet(plug, slot, interfaces.SecurityAppArmor)
c.Assert(err, IsNil)
c.Assert(snippet, IsNil)
}
开发者ID:pedronis,项目名称:snappy,代码行数:28,代码来源:dbus_test.go
示例4: TestSnapTypeCheckConnection
func (s *policySuite) TestSnapTypeCheckConnection(c *C) {
gadgetSnap := snaptest.MockInfo(c, `
name: gadget
type: gadget
plugs:
gadgethelp:
slots:
trustedhelp:
`, nil)
coreSnap := snaptest.MockInfo(c, `
name: core
type: os
slots:
gadgethelp:
trustedhelp:
`, nil)
cand := policy.ConnectCandidate{
Plug: gadgetSnap.Plugs["gadgethelp"],
Slot: coreSnap.Slots["gadgethelp"],
BaseDeclaration: s.baseDecl,
}
c.Check(cand.Check(), IsNil)
cand = policy.ConnectCandidate{
Plug: s.plugSnap.Plugs["gadgethelp"],
Slot: coreSnap.Slots["gadgethelp"],
BaseDeclaration: s.baseDecl,
}
c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
for _, trustedSide := range []*snap.Info{coreSnap, gadgetSnap} {
cand = policy.ConnectCandidate{
Plug: s.plugSnap.Plugs["trustedhelp"],
PlugSnapDeclaration: s.plugDecl,
Slot: trustedSide.Slots["trustedhelp"],
BaseDeclaration: s.baseDecl,
}
c.Check(cand.Check(), IsNil)
}
cand = policy.ConnectCandidate{
Plug: s.plugSnap.Plugs["trustedhelp"],
PlugSnapDeclaration: s.plugDecl,
Slot: s.slotSnap.Slots["trustedhelp"],
BaseDeclaration: s.baseDecl,
}
c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
}
开发者ID:niemeyer,项目名称:snapd,代码行数:50,代码来源:policy_test.go
示例5: TestCheckSnapCheckCallbackOK
func (s *checkSnapSuite) TestCheckSnapCheckCallbackOK(c *C) {
const yaml = `name: foo
version: 1.0`
si := &snap.SideInfo{
SnapID: "snap-id",
}
var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
info := snaptest.MockInfo(c, yaml, si)
return info, nil, nil
}
r1 := snapstate.MockOpenSnapFile(openSnapFile)
defer r1()
checkCbCalled := false
checkCb := func(st *state.State, s, cur *snap.Info, flags snapstate.Flags) error {
c.Assert(s.Name(), Equals, "foo")
c.Assert(s.SnapID, Equals, "snap-id")
checkCbCalled = true
return nil
}
r2 := snapstate.MockCheckSnapCallbacks([]snapstate.CheckSnapCallback{checkCb})
defer r2()
err := snapstate.CheckSnap(s.st, "snap-path", si, nil, snapstate.Flags{})
c.Check(err, IsNil)
c.Check(checkCbCalled, Equals, true)
}
开发者ID:niemeyer,项目名称:snapd,代码行数:30,代码来源:check_snap_test.go
示例6: TestAddSnapComplexErrorHandling
func (s *AddRemoveSuite) TestAddSnapComplexErrorHandling(c *C) {
err := s.repo.AddInterface(&TestInterface{
InterfaceName: "invalid-plug-iface",
SanitizePlugCallback: func(plug *Plug) error { return fmt.Errorf("plug is invalid") },
SanitizeSlotCallback: func(slot *Slot) error { return fmt.Errorf("slot is invalid") },
})
err = s.repo.AddInterface(&TestInterface{
InterfaceName: "invalid-slot-iface",
SanitizePlugCallback: func(plug *Plug) error { return fmt.Errorf("plug is invalid") },
SanitizeSlotCallback: func(slot *Slot) error { return fmt.Errorf("slot is invalid") },
})
snapInfo := snaptest.MockInfo(c, `
name: complex
plugs:
invalid-plug-iface:
unknown-plug-iface:
slots:
invalid-slot-iface:
unknown-slot-iface:
`, nil)
err = s.repo.AddSnap(snapInfo)
c.Check(err, ErrorMatches,
`snap "complex" has bad plugs or slots: invalid-plug-iface \(plug is invalid\); invalid-slot-iface \(slot is invalid\); unknown-plug-iface, unknown-slot-iface \(unknown interface\)`)
// Nothing was added
c.Check(s.repo.Plug("complex", "invalid-plug-iface"), IsNil)
c.Check(s.repo.Plug("complex", "unknown-plug-iface"), IsNil)
c.Check(s.repo.Slot("complex", "invalid-slot-iface"), IsNil)
c.Check(s.repo.Slot("complex", "unknown-slot-iface"), IsNil)
}
开发者ID:clobrano,项目名称:snappy,代码行数:29,代码来源:repo_test.go
示例7: TestConnectedPlugSnippetSimple
func (s *ContentSuite) TestConnectedPlugSnippetSimple(c *C) {
const mockSnapYaml = `name: content-slot-snap
version: 1.0
slots:
content-slot:
interface: content
read:
- shared/read
write:
- shared/write
plugs:
content-plug:
interface: content
target: import
`
info := snaptest.MockInfo(c, mockSnapYaml, nil)
slot := &interfaces.Slot{SlotInfo: info.Slots["content-slot"]}
plug := &interfaces.Plug{PlugInfo: info.Plugs["content-plug"]}
content, err := s.iface.ConnectedPlugSnippet(plug, slot, interfaces.SecurityMount)
c.Assert(err, IsNil)
expected := fmt.Sprintf(`%[1]s/content-slot-snap/unset/shared/read %[1]s/content-slot-snap/unset/import none bind,ro 0 0
%[1]s/content-slot-snap/unset/shared/write %[1]s/content-slot-snap/unset/import none bind 0 0
`, dirs.SnapMountDir)
c.Assert(string(content), DeepEquals, expected)
}
开发者ID:clobrano,项目名称:snappy,代码行数:26,代码来源:content_test.go
示例8: SetUpTest
func (s *BoolFileInterfaceSuite) SetUpTest(c *C) {
info := snaptest.MockInfo(c, `
name: ubuntu-core
slots:
gpio:
interface: bool-file
path: /sys/class/gpio/gpio13/value
led:
interface: bool-file
path: "/sys/class/leds/input27::capslock/brightness"
missing-path: bool-file
bad-path:
interface: bool-file
path: path
parent-dir-path:
interface: bool-file
path: "/sys/class/gpio/../value"
bad-interface-slot: other-interface
plugs:
plug: bool-file
bad-interface-plug: other-interface
`, &snap.SideInfo{})
s.gpioSlot = &interfaces.Slot{SlotInfo: info.Slots["gpio"]}
s.ledSlot = &interfaces.Slot{SlotInfo: info.Slots["led"]}
s.missingPathSlot = &interfaces.Slot{SlotInfo: info.Slots["missing-path"]}
s.badPathSlot = &interfaces.Slot{SlotInfo: info.Slots["bad-path"]}
s.parentDirPathSlot = &interfaces.Slot{SlotInfo: info.Slots["parent-dir-path"]}
s.badInterfaceSlot = &interfaces.Slot{SlotInfo: info.Slots["bad-interface-slot"]}
s.plug = &interfaces.Plug{PlugInfo: info.Plugs["plug"]}
s.badInterfacePlug = &interfaces.Plug{PlugInfo: info.Plugs["bad-interface-plug"]}
}
开发者ID:clobrano,项目名称:snappy,代码行数:31,代码来源:bool_file_test.go
示例9: SetUpTest
func (s *GpioInterfaceSuite) SetUpTest(c *C) {
gadgetInfo := snaptest.MockInfo(c, `
name: my-device
type: gadget
slots:
my-pin:
interface: gpio
number: 100
missing-number:
interface: gpio
bad-number:
interface: gpio
number: forty-two
bad-interface-slot: other-interface
plugs:
plug: gpio
bad-interface-plug: other-interface
`, nil)
s.gadgetGpioSlot = &interfaces.Slot{SlotInfo: gadgetInfo.Slots["my-pin"]}
s.gadgetMissingNumberSlot = &interfaces.Slot{SlotInfo: gadgetInfo.Slots["missing-number"]}
s.gadgetBadNumberSlot = &interfaces.Slot{SlotInfo: gadgetInfo.Slots["bad-number"]}
s.gadgetBadInterfaceSlot = &interfaces.Slot{SlotInfo: gadgetInfo.Slots["bad-interface-slot"]}
s.gadgetPlug = &interfaces.Plug{PlugInfo: gadgetInfo.Plugs["plug"]}
s.gadgetBadInterfacePlug = &interfaces.Plug{PlugInfo: gadgetInfo.Plugs["bad-interface-plug"]}
osInfo := snaptest.MockInfo(c, `
name: my-core
type: os
slots:
my-pin:
interface: gpio
number: 777
direction: out
`, nil)
s.osGpioSlot = &interfaces.Slot{SlotInfo: osInfo.Slots["my-pin"]}
appInfo := snaptest.MockInfo(c, `
name: my-app
slots:
my-pin:
interface: gpio
number: 154
direction: out
`, nil)
s.appGpioSlot = &interfaces.Slot{SlotInfo: appInfo.Slots["my-pin"]}
}
开发者ID:niemeyer,项目名称:snapd,代码行数:46,代码来源:gpio_test.go
示例10: TestConnectionBoth
func (s *DbusInterfaceSuite) TestConnectionBoth(c *C) {
const plugYaml = `name: plugger
version: 1.0
plugs:
that:
interface: dbus
bus: system
name: org.slotter.other-session
this:
interface: dbus
bus: session
name: org.slotter.session
`
const slotYaml = `name: slotter
version: 1.0
slots:
this:
interface: dbus
bus: session
name: org.slotter.session
that:
interface: dbus
bus: system
name: org.slotter.other-session
`
plugInfo := snaptest.MockInfo(c, plugYaml, nil)
matchingPlug1 := &interfaces.Plug{PlugInfo: plugInfo.Plugs["this"]}
matchingPlug2 := &interfaces.Plug{PlugInfo: plugInfo.Plugs["that"]}
slotInfo := snaptest.MockInfo(c, slotYaml, nil)
matchingSlot1 := &interfaces.Slot{SlotInfo: slotInfo.Slots["this"]}
matchingSlot2 := &interfaces.Slot{SlotInfo: slotInfo.Slots["that"]}
snippet, err := s.iface.ConnectedPlugSnippet(matchingPlug1, matchingSlot1, interfaces.SecurityAppArmor)
c.Assert(err, IsNil)
c.Assert(snippet, Not(IsNil))
c.Check(string(snippet), testutil.Contains, "org.slotter.session")
c.Check(string(snippet), testutil.Contains, "bus=session")
snippet, err = s.iface.ConnectedPlugSnippet(matchingPlug2, matchingSlot2, interfaces.SecurityAppArmor)
c.Assert(err, IsNil)
c.Assert(snippet, Not(IsNil))
c.Check(string(snippet), testutil.Contains, "org.slotter.other-session")
c.Check(string(snippet), testutil.Contains, "bus=system")
}
开发者ID:pedronis,项目名称:snappy,代码行数:46,代码来源:dbus_test.go
示例11: TestDollarPlugPublisherIDCheckConnection
func (s *policySuite) TestDollarPlugPublisherIDCheckConnection(c *C) {
// no known publishers
cand := policy.ConnectCandidate{
Plug: s.plugSnap.Plugs["same-plug-publisher-id"],
Slot: s.randomSnap.Slots["same-plug-publisher-id"],
BaseDeclaration: s.baseDecl,
}
c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
// no slot-side declaration
cand = policy.ConnectCandidate{
Plug: s.plugSnap.Plugs["same-plug-publisher-id"],
PlugSnapDeclaration: s.plugDecl,
Slot: s.randomSnap.Slots["same-plug-publisher-id"],
BaseDeclaration: s.baseDecl,
}
c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
// slot-side declaration, wrong publisher-id
cand = policy.ConnectCandidate{
Plug: s.plugSnap.Plugs["same-plug-publisher-id"],
PlugSnapDeclaration: s.plugDecl,
Slot: s.randomSnap.Slots["same-plug-publisher-id"],
SlotSnapDeclaration: s.randomDecl,
BaseDeclaration: s.baseDecl,
}
c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
// slot publisher id == plug publisher id
samePubSlotSnap := snaptest.MockInfo(c, `
name: same-pub-slot-snap
slots:
same-plug-publisher-id:
`, nil)
a, err := asserts.Decode([]byte(`type: snap-declaration
authority-id: canonical
series: 16
snap-name: same-pub-slot-snap
snap-id: samepublslotsnapidididididididid
publisher-id: plug-publisher
timestamp: 2016-09-30T12:00:00Z
sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
AXNpZw==`))
c.Assert(err, IsNil)
samePubSlotDecl := a.(*asserts.SnapDeclaration)
cand = policy.ConnectCandidate{
Plug: s.plugSnap.Plugs["same-plug-publisher-id"],
PlugSnapDeclaration: s.plugDecl,
Slot: samePubSlotSnap.Slots["same-plug-publisher-id"],
SlotSnapDeclaration: samePubSlotDecl,
BaseDeclaration: s.baseDecl,
}
c.Check(cand.Check(), IsNil)
}
开发者ID:niemeyer,项目名称:snapd,代码行数:57,代码来源:policy_test.go
示例12: TestAutoConnectBlacklist
func (s *RepositorySuite) TestAutoConnectBlacklist(c *C) {
// Add two interfaces, one with automatic connections, one with manual
repo := s.emptyRepo
err := repo.AddInterface(&TestInterface{InterfaceName: "auto", AutoConnectFlag: true})
c.Assert(err, IsNil)
err = repo.AddInterface(&TestInterface{InterfaceName: "manual"})
c.Assert(err, IsNil)
// Add a pair of snaps with plugs/slots using those two interfaces
consumer := snaptest.MockInfo(c, `
name: consumer
plugs:
auto:
manual:
`, nil)
producer := snaptest.MockInfo(c, `
name: producer
type: os
slots:
auto:
manual:
`, nil)
err = repo.AddSnap(producer)
c.Assert(err, IsNil)
err = repo.AddSnap(consumer)
c.Assert(err, IsNil)
// Sanity check, our test is valid because plug "auto" is a candidate
// for auto-connection
c.Assert(repo.AutoConnectCandidates("consumer", "auto"), HasLen, 1)
// Without any connections in place, the plug "auto" is blacklisted
// because in normal circumstances it would be auto-connected.
blacklist := repo.AutoConnectBlacklist("consumer")
c.Check(blacklist, DeepEquals, map[string]bool{"auto": true})
// Connect the "auto" plug and slots together
err = repo.Connect("consumer", "auto", "producer", "auto")
c.Assert(err, IsNil)
// With the connection in place the "auto" plug is not blacklisted.
blacklist = repo.AutoConnectBlacklist("consumer")
c.Check(blacklist, IsNil)
}
开发者ID:clobrano,项目名称:snappy,代码行数:44,代码来源:repo_test.go
示例13: InstallSnap
// InstallSnap "installs" a snap from YAML.
func (s *BackendSuite) InstallSnap(c *C, opts interfaces.ConfinementOptions, snapYaml string, revision int) *snap.Info {
snapInfo := snaptest.MockInfo(c, snapYaml, &snap.SideInfo{
Revision: snap.R(revision),
Developer: "acme",
})
s.addPlugsSlots(c, snapInfo)
err := s.Backend.Setup(snapInfo, opts, s.Repo)
c.Assert(err, IsNil)
return snapInfo
}
开发者ID:pedronis,项目名称:snappy,代码行数:11,代码来源:backendtest.go
示例14: TestResolveSpecialVariable
func (s *ContentSuite) TestResolveSpecialVariable(c *C) {
info := snaptest.MockInfo(c, "name: name", &snap.SideInfo{Revision: snap.R(42)})
c.Check(builtin.ResolveSpecialVariable("foo", info), Equals, "/snap/name/42/foo")
c.Check(builtin.ResolveSpecialVariable("$SNAP/foo", info), Equals, "/snap/name/42/foo")
c.Check(builtin.ResolveSpecialVariable("$SNAP_DATA/foo", info), Equals, "/var/snap/name/42/foo")
c.Check(builtin.ResolveSpecialVariable("$SNAP_COMMON/foo", info), Equals, "/var/snap/name/common/foo")
c.Check(builtin.ResolveSpecialVariable("$SNAP", info), Equals, "/snap/name/42")
c.Check(builtin.ResolveSpecialVariable("$SNAP_DATA", info), Equals, "/var/snap/name/42")
c.Check(builtin.ResolveSpecialVariable("$SNAP_COMMON", info), Equals, "/var/snap/name/common")
}
开发者ID:elopio,项目名称:snappy,代码行数:10,代码来源:content_test.go
示例15: InstallSnap
// InstallSnap "installs" a snap from YAML.
func (s *BackendSuite) InstallSnap(c *C, devMode bool, snapYaml string, revision int) *snap.Info {
snapInfo := snaptest.MockInfo(c, snapYaml, &snap.SideInfo{
Revision: snap.R(revision),
Developer: "acme",
})
s.addPlugsSlots(c, snapInfo)
err := s.Backend.Setup(snapInfo, devMode, s.Repo)
c.Assert(err, IsNil)
return snapInfo
}
开发者ID:clobrano,项目名称:snappy,代码行数:11,代码来源:backendtest.go
示例16: TestSanitizeSlotNoPaths
func (s *ContentSuite) TestSanitizeSlotNoPaths(c *C) {
const mockSnapYaml = `name: content-slot-snap
version: 1.0
slots:
content-slot:
interface: content
`
info := snaptest.MockInfo(c, mockSnapYaml, nil)
slot := &interfaces.Slot{SlotInfo: info.Slots["content-slot"]}
err := s.iface.SanitizeSlot(slot)
c.Assert(err, ErrorMatches, "read or write path must be set")
}
开发者ID:clobrano,项目名称:snappy,代码行数:12,代码来源:content_test.go
示例17: connectCand
func (s *baseDeclSuite) connectCand(c *C, iface, slotYaml, plugYaml string) *policy.ConnectCandidate {
if slotYaml == "" {
slotYaml = fmt.Sprintf(`name: slot-snap
slots:
%s:
`, iface)
}
if plugYaml == "" {
plugYaml = fmt.Sprintf(`name: plug-snap
plugs:
%s:
`, iface)
}
slotSnap := snaptest.MockInfo(c, slotYaml, nil)
plugSnap := snaptest.MockInfo(c, plugYaml, nil)
return &policy.ConnectCandidate{
Plug: plugSnap.Plugs[iface],
Slot: slotSnap.Slots[iface],
BaseDeclaration: s.baseDecl,
}
}
开发者ID:chipaca,项目名称:snappy,代码行数:21,代码来源:basedeclaration_test.go
示例18: TestSanitizePlugSimpleNoTarget
func (s *ContentSuite) TestSanitizePlugSimpleNoTarget(c *C) {
const mockSnapYaml = `name: content-slot-snap
version: 1.0
plugs:
content-plug:
interface: content
`
info := snaptest.MockInfo(c, mockSnapYaml, nil)
plug := &interfaces.Plug{PlugInfo: info.Plugs["content-plug"]}
err := s.iface.SanitizePlug(plug)
c.Assert(err, ErrorMatches, "content plug must contain target path")
}
开发者ID:clobrano,项目名称:snappy,代码行数:12,代码来源:content_test.go
示例19: UpdateSnap
// UpdateSnap "updates" an existing snap from YAML.
func (s *BackendSuite) UpdateSnap(c *C, oldSnapInfo *snap.Info, devMode bool, snapYaml string, revision int) *snap.Info {
newSnapInfo := snaptest.MockInfo(c, snapYaml, &snap.SideInfo{
Revision: snap.R(revision),
Developer: "acme",
})
c.Assert(newSnapInfo.Name(), Equals, oldSnapInfo.Name())
s.removePlugsSlots(c, oldSnapInfo)
s.addPlugsSlots(c, newSnapInfo)
err := s.Backend.Setup(newSnapInfo, devMode, s.Repo)
c.Assert(err, IsNil)
return newSnapInfo
}
开发者ID:clobrano,项目名称:snappy,代码行数:13,代码来源:backendtest.go
示例20: TestSanitizePlugSimpleTargetRelative
func (s *ContentSuite) TestSanitizePlugSimpleTargetRelative(c *C) {
const mockSnapYaml = `name: content-slot-snap
version: 1.0
plugs:
content-plug:
interface: content
target: ../foo
`
info := snaptest.MockInfo(c, mockSnapYaml, nil)
plug := &interfaces.Plug{PlugInfo: info.Plugs["content-plug"]}
err := s.iface.SanitizePlug(plug)
c.Assert(err, ErrorMatches, "content interface target path is not clean:.*")
}
开发者ID:clobrano,项目名称:snappy,代码行数:13,代码来源:content_test.go
注:本文中的github.com/snapcore/snapd/snap/snaptest.MockInfo函数示例由纯净天空整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。 |
请发表评论