本文整理汇总了Golang中github.com/algoadv/etcd/Godeps/_workspace/src/golang.org/x/net/context.Background函数的典型用法代码示例。如果您正苦于以下问题:Golang Background函数的具体用法?Golang Background怎么用?Golang Background使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了Background函数的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的Golang代码示例。
示例1: TestClientWithMisbehavedServer
func TestClientWithMisbehavedServer(t *testing.T) {
server, ct := setUp(t, 0, math.MaxUint32, misbehaved)
callHdr := &CallHdr{
Host: "localhost",
Method: "foo",
}
conn, ok := ct.(*http2Client)
if !ok {
t.Fatalf("Failed to convert %v to *http2Client", ct)
}
// Test the logic for the violation of stream flow control window size restriction.
s, err := ct.NewStream(context.Background(), callHdr)
if err != nil {
t.Fatalf("Failed to open stream: %v", err)
}
if err := ct.Write(s, expectedRequest, &Options{Last: true, Delay: false}); err != nil {
t.Fatalf("Failed to write: %v", err)
}
// Read without window update.
for {
p := make([]byte, http2MaxFrameLen)
if _, err = s.dec.Read(p); err != nil {
break
}
}
if s.fc.pendingData != initialWindowSize || s.fc.pendingUpdate != 0 || conn.fc.pendingData != initialWindowSize || conn.fc.pendingUpdate != 0 {
t.Fatalf("Client mistakenly updates inbound flow control params: got %d, %d, %d, %d; want %d, %d, %d, %d", s.fc.pendingData, s.fc.pendingUpdate, conn.fc.pendingData, conn.fc.pendingUpdate, initialWindowSize, 0, initialWindowSize, 0)
}
if err != io.EOF || s.statusCode != codes.Internal {
t.Fatalf("Got err %v and the status code %d, want <EOF> and the code %d", err, s.statusCode, codes.Internal)
}
conn.CloseStream(s, err)
if s.fc.pendingData != 0 || s.fc.pendingUpdate != 0 || conn.fc.pendingData != 0 || conn.fc.pendingUpdate != initialWindowSize {
t.Fatalf("Client mistakenly resets inbound flow control params: got %d, %d, %d, %d; want 0, 0, 0, %d", s.fc.pendingData, s.fc.pendingUpdate, conn.fc.pendingData, conn.fc.pendingUpdate, initialWindowSize)
}
// Test the logic for the violation of the connection flow control window size restriction.
//
// Generate enough streams to drain the connection window.
callHdr = &CallHdr{
Host: "localhost",
Method: "foo.MaxFrame",
}
for i := 0; i < int(initialConnWindowSize/initialWindowSize+10); i++ {
s, err := ct.NewStream(context.Background(), callHdr)
if err != nil {
t.Fatalf("Failed to open stream: %v", err)
}
if err := ct.Write(s, expectedRequest, &Options{Last: true, Delay: false}); err != nil {
break
}
}
// http2Client.errChan is closed due to connection flow control window size violation.
<-conn.Error()
ct.Close()
server.stop()
}
开发者ID:algoadv,项目名称:etcd,代码行数:56,代码来源:transport_test.go
示例2: checkCluster
func (d *discovery) checkCluster() ([]*client.Node, int, uint64, error) {
configKey := path.Join("/", d.cluster, "_config")
ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
// find cluster size
resp, err := d.c.Get(ctx, path.Join(configKey, "size"), nil)
cancel()
if err != nil {
if eerr, ok := err.(*client.Error); ok && eerr.Code == client.ErrorCodeKeyNotFound {
return nil, 0, 0, ErrSizeNotFound
}
if err == client.ErrInvalidJSON {
return nil, 0, 0, ErrBadDiscoveryEndpoint
}
if ce, ok := err.(*client.ClusterError); ok {
plog.Error(ce.Detail())
return d.checkClusterRetry()
}
return nil, 0, 0, err
}
size, err := strconv.Atoi(resp.Node.Value)
if err != nil {
return nil, 0, 0, ErrBadSizeKey
}
ctx, cancel = context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
resp, err = d.c.Get(ctx, d.cluster, nil)
cancel()
if err != nil {
if ce, ok := err.(*client.ClusterError); ok {
plog.Error(ce.Detail())
return d.checkClusterRetry()
}
return nil, 0, 0, err
}
nodes := make([]*client.Node, 0)
// append non-config keys to nodes
for _, n := range resp.Node.Nodes {
if !(path.Base(n.Key) == path.Base(configKey)) {
nodes = append(nodes, n)
}
}
snodes := sortableNodes{nodes}
sort.Sort(snodes)
// find self position
for i := range nodes {
if path.Base(nodes[i].Key) == path.Base(d.selfKey()) {
break
}
if i >= size-1 {
return nodes[:size], size, resp.Index, ErrFullCluster
}
}
return nodes, size, resp.Index, nil
}
开发者ID:algoadv,项目名称:etcd,代码行数:56,代码来源:discovery.go
示例3: BenchmarkOneNode
func BenchmarkOneNode(b *testing.B) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
n := newNode()
s := NewMemoryStorage()
r := newTestRaft(1, []uint64{1}, 10, 1, s)
go n.run(r)
defer n.Stop()
n.Campaign(ctx)
go func() {
for i := 0; i < b.N; i++ {
n.Propose(ctx, []byte("foo"))
}
}()
for {
rd := <-n.Ready()
s.Append(rd.Entries)
// a reasonable disk sync latency
time.Sleep(1 * time.Millisecond)
n.Advance()
if rd.HardState.Commit == uint64(b.N+1) {
return
}
}
}
开发者ID:algoadv,项目名称:etcd,代码行数:29,代码来源:node_bench_test.go
示例4: deleteRangeCommandFunc
// deleteRangeCommandFunc executes the "delegeRange" command.
func deleteRangeCommandFunc(c *cli.Context) {
if len(c.Args()) == 0 {
panic("bad arg")
}
var rangeEnd []byte
key := []byte(c.Args()[0])
if len(c.Args()) > 1 {
rangeEnd = []byte(c.Args()[1])
}
conn, err := grpc.Dial(c.GlobalString("endpoint"))
if err != nil {
panic(err)
}
etcd := pb.NewEtcdClient(conn)
req := &pb.DeleteRangeRequest{Key: key, RangeEnd: rangeEnd}
etcd.DeleteRange(context.Background(), req)
if rangeEnd != nil {
fmt.Printf("range [%s, %s) is deleted\n", string(key), string(rangeEnd))
} else {
fmt.Printf("key %s is deleted\n", string(key))
}
}
开发者ID:algoadv,项目名称:etcd,代码行数:26,代码来源:delete_range_command.go
示例5: txnCommandFunc
// txnCommandFunc executes the "txn" command.
func txnCommandFunc(c *cli.Context) {
if len(c.Args()) != 0 {
panic("unexpected args")
}
reader := bufio.NewReader(os.Stdin)
next := compareState
txn := &pb.TxnRequest{}
for next != nil {
next = next(txn, reader)
}
conn, err := grpc.Dial(c.GlobalString("endpoint"))
if err != nil {
panic(err)
}
etcd := pb.NewEtcdClient(conn)
resp, err := etcd.Txn(context.Background(), txn)
if err != nil {
fmt.Println(err)
}
if resp.Succeeded {
fmt.Println("executed success request list")
} else {
fmt.Println("executed failure request list")
}
}
开发者ID:algoadv,项目名称:etcd,代码行数:30,代码来源:txn_command.go
示例6: doCancelAfterFirstResponse
func doCancelAfterFirstResponse(tc testpb.TestServiceClient) {
ctx, cancel := context.WithCancel(context.Background())
stream, err := tc.FullDuplexCall(ctx)
if err != nil {
grpclog.Fatalf("%v.FullDuplexCall(_) = _, %v", tc, err)
}
respParam := []*testpb.ResponseParameters{
{
Size: proto.Int32(31415),
},
}
pl := newPayload(testpb.PayloadType_COMPRESSABLE, 27182)
req := &testpb.StreamingOutputCallRequest{
ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(),
ResponseParameters: respParam,
Payload: pl,
}
if err := stream.Send(req); err != nil {
grpclog.Fatalf("%v.Send(%v) = %v", stream, req, err)
}
if _, err := stream.Recv(); err != nil {
grpclog.Fatalf("%v.Recv() = %v", stream, err)
}
cancel()
if _, err := stream.Recv(); grpc.Code(err) != codes.Canceled {
grpclog.Fatalf("%v compleled with error code %d, want %d", stream, grpc.Code(err), codes.Canceled)
}
grpclog.Println("CancelAfterFirstResponse done")
}
开发者ID:algoadv,项目名称:etcd,代码行数:29,代码来源:client.go
示例7: doClientStreaming
func doClientStreaming(tc testpb.TestServiceClient) {
stream, err := tc.StreamingInputCall(context.Background())
if err != nil {
grpclog.Fatalf("%v.StreamingInputCall(_) = _, %v", tc, err)
}
var sum int
for _, s := range reqSizes {
pl := newPayload(testpb.PayloadType_COMPRESSABLE, s)
req := &testpb.StreamingInputCallRequest{
Payload: pl,
}
if err := stream.Send(req); err != nil {
grpclog.Fatalf("%v.Send(%v) = %v", stream, req, err)
}
sum += s
grpclog.Printf("Sent a request of size %d, aggregated size %d", s, sum)
}
reply, err := stream.CloseAndRecv()
if err != nil {
grpclog.Fatalf("%v.CloseAndRecv() got error %v, want %v", stream, err, nil)
}
if reply.GetAggregatedPayloadSize() != int32(sum) {
grpclog.Fatalf("%v.CloseAndRecv().GetAggregatePayloadSize() = %v; want %v", stream, reply.GetAggregatedPayloadSize(), sum)
}
grpclog.Println("ClientStreaming done")
}
开发者ID:algoadv,项目名称:etcd,代码行数:27,代码来源:client.go
示例8: waitNodes
func (d *discovery) waitNodes(nodes []*client.Node, size int, index uint64) ([]*client.Node, error) {
if len(nodes) > size {
nodes = nodes[:size]
}
// watch from the next index
w := d.c.Watcher(d.cluster, &client.WatcherOptions{AfterIndex: index, Recursive: true})
all := make([]*client.Node, len(nodes))
copy(all, nodes)
for _, n := range all {
if path.Base(n.Key) == path.Base(d.selfKey()) {
plog.Noticef("found self %s in the cluster", path.Base(d.selfKey()))
} else {
plog.Noticef("found peer %s in the cluster", path.Base(n.Key))
}
}
// wait for others
for len(all) < size {
plog.Noticef("found %d peer(s), waiting for %d more", len(all), size-len(all))
resp, err := w.Next(context.Background())
if err != nil {
if ce, ok := err.(*client.ClusterError); ok {
plog.Error(ce.Detail())
return d.waitNodesRetry()
}
return nil, err
}
plog.Noticef("found peer %s in the cluster", path.Base(resp.Node.Key))
all = append(all, resp.Node)
}
plog.Noticef("found %d needed peer(s)", len(all))
return all, nil
}
开发者ID:algoadv,项目名称:etcd,代码行数:33,代码来源:discovery.go
示例9: RemoveMember
func (c *cluster) RemoveMember(t *testing.T, id uint64) {
// send remove request to the cluster
cc := mustNewHTTPClient(t, c.URLs())
ma := client.NewMembersAPI(cc)
ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
if err := ma.Remove(ctx, types.ID(id).String()); err != nil {
t.Fatalf("unexpected remove error %v", err)
}
cancel()
newMembers := make([]*member, 0)
for _, m := range c.Members {
if uint64(m.s.ID()) != id {
newMembers = append(newMembers, m)
} else {
select {
case <-m.s.StopNotify():
m.Terminate(t)
// 1s stop delay + election timeout + 1s disk and network delay + connection write timeout
// TODO: remove connection write timeout by selecting on http response closeNotifier
// blocking on https://github.com/golang/go/issues/9524
case <-time.After(time.Second + time.Duration(electionTicks)*tickDuration + time.Second + rafthttp.ConnWriteTimeout):
t.Fatalf("failed to remove member %s in time", m.s.ID())
}
}
}
c.Members = newMembers
c.waitMembersMatch(t, c.HTTPMembers())
}
开发者ID:algoadv,项目名称:etcd,代码行数:28,代码来源:cluster_test.go
示例10: createSelf
func (d *discovery) createSelf(contents string) error {
ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
resp, err := d.c.Create(ctx, d.selfKey(), contents)
cancel()
if err != nil {
if eerr, ok := err.(client.Error); ok && eerr.Code == client.ErrorCodeNodeExist {
return ErrDuplicateID
}
return err
}
// ensure self appears on the server we connected to
w := d.c.Watcher(d.selfKey(), &client.WatcherOptions{AfterIndex: resp.Node.CreatedIndex - 1})
_, err = w.Next(context.Background())
return err
}
开发者ID:algoadv,项目名称:etcd,代码行数:16,代码来源:discovery.go
示例11: TestHTTPClusterClientDoDeadlineExceedContext
func TestHTTPClusterClientDoDeadlineExceedContext(t *testing.T) {
fakeURL := url.URL{}
tr := newFakeTransport()
tr.finishCancel <- struct{}{}
c := &httpClusterClient{
clientFactory: newHTTPClientFactory(tr, DefaultCheckRedirect, 0),
endpoints: []url.URL{fakeURL},
}
errc := make(chan error)
go func() {
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
defer cancel()
_, _, err := c.Do(ctx, &fakeAction{})
errc <- err
}()
select {
case err := <-errc:
if err != context.DeadlineExceeded {
t.Errorf("err = %+v, want %+v", err, context.DeadlineExceeded)
}
case <-time.After(time.Second):
t.Fatalf("unexpected timeout when waitting for request to deadline exceed")
}
}
开发者ID:algoadv,项目名称:etcd,代码行数:26,代码来源:client_test.go
示例12: TestSimpleHTTPClientDoCancelContextResponseBodyClosed
func TestSimpleHTTPClientDoCancelContextResponseBodyClosed(t *testing.T) {
tr := newFakeTransport()
c := &simpleHTTPClient{transport: tr}
// create an already-cancelled context
ctx, cancel := context.WithCancel(context.Background())
cancel()
body := &checkableReadCloser{ReadCloser: ioutil.NopCloser(strings.NewReader("foo"))}
go func() {
// wait that simpleHTTPClient knows the context is already timed out,
// and calls CancelRequest
testutil.WaitSchedule()
// response is returned before cancel effects
tr.respchan <- &http.Response{Body: body}
}()
_, _, err := c.Do(ctx, &fakeAction{})
if err == nil {
t.Fatalf("expected non-nil error, got nil")
}
if !body.closed {
t.Fatalf("expected closed body")
}
}
开发者ID:algoadv,项目名称:etcd,代码行数:27,代码来源:client_test.go
示例13: testClientStreaming
func testClientStreaming(t *testing.T, e env) {
s, cc := setUp(math.MaxUint32, e)
tc := testpb.NewTestServiceClient(cc)
defer tearDown(s, cc)
stream, err := tc.StreamingInputCall(context.Background())
if err != nil {
t.Fatalf("%v.StreamingInputCall(_) = _, %v, want <nil>", tc, err)
}
var sum int
for _, s := range reqSizes {
pl := newPayload(testpb.PayloadType_COMPRESSABLE, int32(s))
req := &testpb.StreamingInputCallRequest{
Payload: pl,
}
if err := stream.Send(req); err != nil {
t.Fatalf("%v.Send(%v) = %v, want <nil>", stream, req, err)
}
sum += s
}
reply, err := stream.CloseAndRecv()
if err != nil {
t.Fatalf("%v.CloseAndRecv() got error %v, want %v", stream, err, nil)
}
if reply.GetAggregatedPayloadSize() != int32(sum) {
t.Fatalf("%v.CloseAndRecv().GetAggregatePayloadSize() = %v; want %v", stream, reply.GetAggregatedPayloadSize(), sum)
}
}
开发者ID:algoadv,项目名称:etcd,代码行数:27,代码来源:end2end_test.go
示例14: TestHTTPMembersAPIListSuccess
func TestHTTPMembersAPIListSuccess(t *testing.T) {
wantAction := &membersAPIActionList{}
mAPI := &httpMembersAPI{
client: &actionAssertingHTTPClient{
t: t,
act: wantAction,
resp: http.Response{
StatusCode: http.StatusOK,
},
body: []byte(`{"members":[{"id":"94088180e21eb87b","name":"node2","peerURLs":["http://127.0.0.1:7002"],"clientURLs":["http://127.0.0.1:4002"]}]}`),
},
}
wantResponseMembers := []Member{
{
ID: "94088180e21eb87b",
Name: "node2",
PeerURLs: []string{"http://127.0.0.1:7002"},
ClientURLs: []string{"http://127.0.0.1:4002"},
},
}
m, err := mAPI.List(context.Background())
if err != nil {
t.Errorf("got non-nil err: %#v", err)
}
if !reflect.DeepEqual(wantResponseMembers, m) {
t.Errorf("incorrect Members: want=%#v got=%#v", wantResponseMembers, m)
}
}
开发者ID:algoadv,项目名称:etcd,代码行数:30,代码来源:members_test.go
示例15: TestHTTPMembersAPIListError
func TestHTTPMembersAPIListError(t *testing.T) {
tests := []httpClient{
// generic httpClient failure
&staticHTTPClient{err: errors.New("fail!")},
// unrecognized HTTP status code
&staticHTTPClient{
resp: http.Response{StatusCode: http.StatusTeapot},
},
// fail to unmarshal body on StatusOK
&staticHTTPClient{
resp: http.Response{
StatusCode: http.StatusOK,
},
body: []byte(`[{"id":"XX`),
},
}
for i, tt := range tests {
mAPI := &httpMembersAPI{client: tt}
ms, err := mAPI.List(context.Background())
if err == nil {
t.Errorf("#%d: got nil err", i)
}
if ms != nil {
t.Errorf("#%d: got non-nil Member slice", i)
}
}
}
开发者ID:algoadv,项目名称:etcd,代码行数:30,代码来源:members_test.go
示例16: performOneRPC
func performOneRPC(ct ClientTransport) {
callHdr := &CallHdr{
Host: "localhost",
Method: "foo.Small",
}
s, err := ct.NewStream(context.Background(), callHdr)
if err != nil {
return
}
opts := Options{
Last: true,
Delay: false,
}
if err := ct.Write(s, expectedRequest, &opts); err == nil {
time.Sleep(5 * time.Millisecond)
// The following s.Recv()'s could error out because the
// underlying transport is gone.
//
// Read response
p := make([]byte, len(expectedResponse))
io.ReadFull(s, p)
// Read io.EOF
io.ReadFull(s, p)
}
}
开发者ID:algoadv,项目名称:etcd,代码行数:25,代码来源:transport_test.go
示例17: TestHTTPMembersAPIAddSuccess
func TestHTTPMembersAPIAddSuccess(t *testing.T) {
wantAction := &membersAPIActionAdd{
peerURLs: types.URLs([]url.URL{
{Scheme: "http", Host: "127.0.0.1:7002"},
}),
}
mAPI := &httpMembersAPI{
client: &actionAssertingHTTPClient{
t: t,
act: wantAction,
resp: http.Response{
StatusCode: http.StatusCreated,
},
body: []byte(`{"id":"94088180e21eb87b","peerURLs":["http://127.0.0.1:7002"]}`),
},
}
wantResponseMember := &Member{
ID: "94088180e21eb87b",
PeerURLs: []string{"http://127.0.0.1:7002"},
}
m, err := mAPI.Add(context.Background(), "http://127.0.0.1:7002")
if err != nil {
t.Errorf("got non-nil err: %#v", err)
}
if !reflect.DeepEqual(wantResponseMember, m) {
t.Errorf("incorrect Member: want=%#v got=%#v", wantResponseMember, m)
}
}
开发者ID:algoadv,项目名称:etcd,代码行数:31,代码来源:members_test.go
示例18: addMember
func (c *cluster) addMember(t *testing.T, usePeerTLS bool) {
m := mustNewMember(t, c.name(rand.Int()), usePeerTLS)
scheme := "http"
if usePeerTLS {
scheme = "https"
}
// send add request to the cluster
cc := mustNewHTTPClient(t, []string{c.URL(0)})
ma := client.NewMembersAPI(cc)
ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
peerURL := scheme + "://" + m.PeerListeners[0].Addr().String()
if _, err := ma.Add(ctx, peerURL); err != nil {
t.Fatalf("add member on %s error: %v", c.URL(0), err)
}
cancel()
// wait for the add node entry applied in the cluster
members := append(c.HTTPMembers(), client.Member{PeerURLs: []string{peerURL}, ClientURLs: []string{}})
c.waitMembersMatch(t, members)
m.InitialPeerURLsMap = types.URLsMap{}
for _, mm := range c.Members {
m.InitialPeerURLsMap[mm.Name] = mm.PeerURLs
}
m.InitialPeerURLsMap[m.Name] = m.PeerURLs
m.NewCluster = false
if err := m.Launch(); err != nil {
t.Fatal(err)
}
c.Members = append(c.Members, m)
// wait cluster to be stable to receive future client requests
c.waitMembersMatch(t, c.HTTPMembers())
}
开发者ID:algoadv,项目名称:etcd,代码行数:34,代码来源:cluster_test.go
示例19: TestIssue2904
// Ensure etcd will not panic when removing a just started member.
func TestIssue2904(t *testing.T) {
defer afterTest(t)
// start 1-member cluster to ensure member 0 is the leader of the cluster.
c := NewCluster(t, 1)
c.Launch(t)
defer c.Terminate(t)
c.AddMember(t)
c.Members[1].Stop(t)
// send remove member-1 request to the cluster.
cc := mustNewHTTPClient(t, c.URLs())
ma := client.NewMembersAPI(cc)
ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
// the proposal is not committed because member 1 is stopped, but the
// proposal is appended to leader's raft log.
ma.Remove(ctx, c.Members[1].s.ID().String())
cancel()
// restart member, and expect it to send updateAttr request.
// the log in the leader is like this:
// [..., remove 1, ..., update attr 1, ...]
c.Members[1].Restart(t)
// when the member comes back, it ack the proposal to remove itself,
// and apply it.
<-c.Members[1].s.StopNotify()
// terminate removed member
c.Members[1].Terminate(t)
c.Members = c.Members[:1]
// wait member to be removed.
c.waitMembersMatch(t, c.HTTPMembers())
}
开发者ID:algoadv,项目名称:etcd,代码行数:34,代码来源:cluster_test.go
示例20: TestLargeMessage
func TestLargeMessage(t *testing.T) {
server, ct := setUp(t, 0, math.MaxUint32, normal)
callHdr := &CallHdr{
Host: "localhost",
Method: "foo.Large",
}
var wg sync.WaitGroup
for i := 0; i < 2; i++ {
wg.Add(1)
go func() {
s, err := ct.NewStream(context.Background(), callHdr)
if err != nil {
t.Fatalf("failed to open stream: %v", err)
}
if err := ct.Write(s, expectedRequestLarge, &Options{Last: true, Delay: false}); err != nil {
t.Fatalf("failed to send data: %v", err)
}
p := make([]byte, len(expectedResponseLarge))
_, recvErr := io.ReadFull(s, p)
if recvErr != nil || !bytes.Equal(p, expectedResponseLarge) {
t.Fatalf("Error: %v, want <nil>; Result len: %d, want len %d", recvErr, len(p), len(expectedResponseLarge))
}
_, recvErr = io.ReadFull(s, p)
if recvErr != io.EOF {
t.Fatalf("Error: %v; want <EOF>", recvErr)
}
wg.Done()
}()
}
wg.Wait()
ct.Close()
server.stop()
}
开发者ID:algoadv,项目名称:etcd,代码行数:33,代码来源:transport_test.go
注:本文中的github.com/algoadv/etcd/Godeps/_workspace/src/golang.org/x/net/context.Background函数示例整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。 |
请发表评论