Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
4d031abc
Commit
4d031abc
authored
May 13, 2015
by
Kris Rousey
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Changing the implementation of DeepCopy to use reflection instead of Gob encode/decode.
parent
3481db8a
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
153 additions
and
37 deletions
+153
-37
copy_test.go
pkg/api/copy_test.go
+52
-0
deep_copy.go
pkg/conversion/deep_copy.go
+83
-37
deep_copy_test.go
pkg/conversion/deep_copy_test.go
+18
-0
No files found.
pkg/api/copy_test.go
0 → 100644
View file @
4d031abc
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
api_test
import
(
"math/rand"
"reflect"
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi"
apitesting
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
)
func
TestDeepCopyApiObjects
(
t
*
testing
.
T
)
{
for
i
:=
0
;
i
<
*
fuzzIters
;
i
++
{
for
_
,
version
:=
range
[]
string
{
""
,
testapi
.
Version
()}
{
f
:=
apitesting
.
FuzzerFor
(
t
,
version
,
rand
.
NewSource
(
rand
.
Int63
()))
for
kind
:=
range
api
.
Scheme
.
KnownTypes
(
version
)
{
item
,
err
:=
api
.
Scheme
.
New
(
version
,
kind
)
if
err
!=
nil
{
t
.
Fatalf
(
"Could not create a %s: %s"
,
kind
,
err
)
}
f
.
Fuzz
(
item
)
itemCopy
,
err
:=
conversion
.
DeepCopy
(
item
)
if
err
!=
nil
{
t
.
Errorf
(
"Could not deep copy a %s: %s"
,
kind
,
err
)
continue
}
if
!
reflect
.
DeepEqual
(
item
,
itemCopy
)
{
t
.
Errorf
(
"expected %#v
\n
got %#v"
,
item
,
itemCopy
)
}
}
}
}
}
pkg/conversion/deep_copy.go
View file @
4d031abc
...
@@ -17,52 +17,98 @@ limitations under the License.
...
@@ -17,52 +17,98 @@ limitations under the License.
package
conversion
package
conversion
import
(
import
(
"bytes"
"fmt"
"encoding/gob"
"reflect"
"reflect"
"sync"
)
)
// pool is a pool of copiers
var
pool
=
sync
.
Pool
{
New
:
func
()
interface
{}
{
return
newGobCopier
()
},
}
// DeepCopy makes a deep copy of source or returns an error.
// DeepCopy makes a deep copy of source or returns an error.
func
DeepCopy
(
source
interface
{})
(
interface
{},
error
)
{
func
DeepCopy
(
source
interface
{})
(
interface
{},
error
)
{
v
:=
reflect
.
New
(
reflect
.
TypeOf
(
source
))
v
,
err
:=
deepCopy
(
reflect
.
ValueOf
(
source
))
return
v
.
Interface
(),
err
}
c
:=
pool
.
Get
()
.
(
gobCopier
)
func
deepCopy
(
src
reflect
.
Value
)
(
reflect
.
Value
,
error
)
{
defer
pool
.
Put
(
c
)
switch
src
.
Kind
()
{
if
err
:=
c
.
CopyInto
(
v
.
Interface
(),
source
);
err
!=
nil
{
case
reflect
.
Chan
,
reflect
.
Func
,
reflect
.
UnsafePointer
,
reflect
.
Uintptr
:
return
nil
,
err
return
src
,
fmt
.
Errorf
(
"cannot deep copy kind: %s"
,
src
.
Kind
())
}
return
v
.
Elem
()
.
Interface
(),
nil
case
reflect
.
Array
:
}
dst
:=
reflect
.
New
(
src
.
Type
())
for
i
:=
0
;
i
<
src
.
Len
();
i
++
{
copyVal
,
err
:=
deepCopy
(
src
.
Index
(
i
))
if
err
!=
nil
{
return
src
,
err
}
dst
.
Elem
()
.
Index
(
i
)
.
Set
(
copyVal
)
}
return
dst
.
Elem
(),
nil
// gobCopier provides a copy mechanism for objects using Gob.
case
reflect
.
Interface
:
// This object is not safe for multiple threads because buffer
if
src
.
IsNil
()
{
// is shared.
return
src
,
nil
type
gobCopier
struct
{
}
enc
*
gob
.
Encoder
return
deepCopy
(
src
.
Elem
())
dec
*
gob
.
Decoder
}
func
newGobCopier
()
gobCopier
{
case
reflect
.
Map
:
buf
:=
&
bytes
.
Buffer
{}
if
src
.
IsNil
()
{
return
gobCopier
{
return
src
,
nil
enc
:
gob
.
NewEncoder
(
buf
),
}
dec
:
gob
.
NewDecoder
(
buf
),
dst
:=
reflect
.
MakeMap
(
src
.
Type
())
}
for
_
,
k
:=
range
src
.
MapKeys
()
{
}
copyVal
,
err
:=
deepCopy
(
src
.
MapIndex
(
k
))
if
err
!=
nil
{
return
src
,
err
}
dst
.
SetMapIndex
(
k
,
copyVal
)
}
return
dst
,
nil
func
(
c
*
gobCopier
)
CopyInto
(
dst
,
src
interface
{})
error
{
case
reflect
.
Ptr
:
if
err
:=
c
.
enc
.
Encode
(
src
);
err
!=
nil
{
if
src
.
IsNil
()
{
return
err
return
src
,
nil
}
}
if
err
:=
c
.
dec
.
Decode
(
dst
);
err
!=
nil
{
dst
:=
reflect
.
New
(
src
.
Type
()
.
Elem
())
return
err
copyVal
,
err
:=
deepCopy
(
src
.
Elem
())
if
err
!=
nil
{
return
src
,
err
}
dst
.
Elem
()
.
Set
(
copyVal
)
return
dst
,
nil
case
reflect
.
Slice
:
if
src
.
IsNil
()
{
return
src
,
nil
}
dst
:=
reflect
.
MakeSlice
(
src
.
Type
(),
0
,
src
.
Len
())
for
i
:=
0
;
i
<
src
.
Len
();
i
++
{
copyVal
,
err
:=
deepCopy
(
src
.
Index
(
i
))
if
err
!=
nil
{
return
src
,
err
}
dst
=
reflect
.
Append
(
dst
,
copyVal
)
}
return
dst
,
nil
case
reflect
.
Struct
:
dst
:=
reflect
.
New
(
src
.
Type
())
for
i
:=
0
;
i
<
src
.
NumField
();
i
++
{
if
!
dst
.
Elem
()
.
Field
(
i
)
.
CanSet
()
{
// Can't set private fields. At this point, the
// best we can do is a shallow copy. For
// example, time.Time is a value type with
// private members that can be shallow copied.
return
src
,
nil
}
copyVal
,
err
:=
deepCopy
(
src
.
Field
(
i
))
if
err
!=
nil
{
return
src
,
err
}
dst
.
Elem
()
.
Field
(
i
)
.
Set
(
copyVal
)
}
return
dst
.
Elem
(),
nil
default
:
// Value types like numbers, booleans, and strings.
return
src
,
nil
}
}
return
nil
}
}
pkg/conversion/deep_copy_test.go
View file @
4d031abc
...
@@ -108,6 +108,24 @@ func TestDeepCopyPointerSeparate(t *testing.T) {
...
@@ -108,6 +108,24 @@ func TestDeepCopyPointerSeparate(t *testing.T) {
}
}
}
}
func
TestDeepCopyStruct
(
t
*
testing
.
T
)
{
type
Foo
struct
{
A
int
}
type
Bar
struct
{
Foo
F
*
Foo
}
a
:=
&
Bar
{
Foo
{
1
},
&
Foo
{
2
}}
b
:=
copyOrDie
(
t
,
a
)
.
(
*
Bar
)
a
.
A
=
3
a
.
F
.
A
=
4
if
b
.
A
!=
1
||
b
.
F
.
A
!=
2
{
t
.
Errorf
(
"deep copy wasn't deep: %#v, %#v"
,
a
,
b
)
}
}
var
result
interface
{}
var
result
interface
{}
func
BenchmarkDeepCopy
(
b
*
testing
.
B
)
{
func
BenchmarkDeepCopy
(
b
*
testing
.
B
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment