完成循环链表的单元测试
This commit is contained in:
parent
c0a81a3c5f
commit
34c1468578
84
config.go
84
config.go
|
@ -1,22 +1,62 @@
|
|||
package imitate
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// YamlCurls 为了自定义序列化函数
|
||||
type YamlCurls []string
|
||||
|
||||
// UnmarshalYAML YamlCurls反序列化函数
|
||||
func (curls *YamlCurls) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
|
||||
var buf interface{}
|
||||
err := unmarshal(&buf)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch tbuf := buf.(type) {
|
||||
case string:
|
||||
*curls = append(*curls, parseCurl(tbuf))
|
||||
case []interface{}:
|
||||
for _, ifa := range tbuf {
|
||||
*curls = append(*curls, parseCurl(ifa.(string)))
|
||||
}
|
||||
default:
|
||||
return errors.New("read curls is error, " + reflect.TypeOf(buf).String())
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalYAML 序列化函数
|
||||
func (curls *YamlCurls) MarshalYAML() (interface{}, error) {
|
||||
content := "["
|
||||
for _, curl := range []string(*curls) {
|
||||
content += "\"" + curl + "\"" + ", "
|
||||
}
|
||||
content = strings.TrimRight(content, ", ")
|
||||
content += "]"
|
||||
return content, nil
|
||||
}
|
||||
|
||||
// Config 任务加载的默认配置
|
||||
type Config struct {
|
||||
Session int `yaml:"session"`
|
||||
Mode int `yaml:"mode"`
|
||||
Proxies []string `yaml:"proxies"`
|
||||
Retry int `yaml:"retry"`
|
||||
Priority int `yaml:"priority"`
|
||||
Curl string `yaml:"curl"`
|
||||
Session int `yaml:"session"`
|
||||
Mode int `yaml:"mode"`
|
||||
Proxies []string `yaml:"proxies"`
|
||||
Retry int `yaml:"retry"`
|
||||
Priority int `yaml:"priority"`
|
||||
Curls YamlCurls `yaml:"curls"`
|
||||
|
||||
ExecuteInterval `yaml:"execute_interval"`
|
||||
ExecuteAt `yaml:"execute_at"`
|
||||
|
@ -76,21 +116,21 @@ func NewConfig(p string) *Config {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// spew.Dump(conf)
|
||||
|
||||
if conf.Curl == "" {
|
||||
log.Println("the path ", p, "curl is \"\"")
|
||||
} else {
|
||||
if conf.Curl[0] == '@' {
|
||||
curlfile, err := os.Open(conf.Curl[1:])
|
||||
defer curlfile.Close()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
curldata, err := ioutil.ReadAll(curlfile)
|
||||
conf.Curl = strings.Trim(string(curldata), "\r\n ")
|
||||
}
|
||||
}
|
||||
spew.Dump(conf)
|
||||
|
||||
return conf
|
||||
}
|
||||
|
||||
func parseCurl(curl string) string {
|
||||
if curl[0] == '@' {
|
||||
curlfile, err := os.Open(curl[1:])
|
||||
defer curlfile.Close()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
curldata, err := ioutil.ReadAll(curlfile)
|
||||
return strings.Trim(string(curldata), "\r\n ")
|
||||
}
|
||||
|
||||
return strings.Trim(curl, "\r\n ")
|
||||
}
|
||||
|
|
|
@ -34,6 +34,13 @@ type PlanResult struct {
|
|||
Resp *requests.Response
|
||||
}
|
||||
|
||||
// NewExecutePlan create a plan
|
||||
func NewExecutePlan() *ExecutePlan {
|
||||
plan := &ExecutePlan{}
|
||||
|
||||
return plan
|
||||
}
|
||||
|
||||
// AppendIExecute 添加执行计划任务
|
||||
func (ep *ExecutePlan) AppendIExecute(e IExecute) {
|
||||
ep.ExecuteQueue = append(ep.ExecuteQueue, e)
|
||||
|
|
|
@ -15,13 +15,23 @@ type Person struct {
|
|||
}
|
||||
|
||||
type Task struct {
|
||||
GURL *curl2info.CURL
|
||||
Curl *curl2info.CURL
|
||||
Conf *Config
|
||||
Plan *ExecutePlan
|
||||
}
|
||||
|
||||
func NewTask(conf string, curlinfo string) *Task {
|
||||
task := &Task{}
|
||||
|
||||
task.Conf = NewConfig(conf)
|
||||
task.Curl = curl2info.NewCURL(curlinfo)
|
||||
|
||||
return task
|
||||
}
|
||||
|
||||
func TestNewYaml(t *testing.T) {
|
||||
data := spew.Sdump(NewConfig("test.yaml"))
|
||||
if !(regexp.MustCompile(`Device: \(string\) \(len=12\) "eson-OnePlus"`).MatchString(data) && regexp.MustCompile(`Sec: \(int\) 30`).MatchString(data)) {
|
||||
if !(regexp.MustCompile(`Device: \(string\) \(len=12\) "eson-OnePlus"`).MatchString(data) && regexp.MustCompile(`Sec: \(int\) 30`).MatchString(data) && regexp.MustCompile(`http://is.snssdk.com/2/article/information/v24/\?`).MatchString(data)) {
|
||||
t.Error(data)
|
||||
}
|
||||
}
|
||||
|
@ -41,3 +51,7 @@ func TestExecute(t *testing.T) {
|
|||
log.Println(resp.Content())
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecutePlan(t *testing.T) {
|
||||
|
||||
}
|
||||
|
|
210
structure.go
Normal file
210
structure.go
Normal file
|
@ -0,0 +1,210 @@
|
|||
package imitate
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
)
|
||||
|
||||
// Node 循环链表 三色标记 不确定是否会清除循环引用, 网上说会
|
||||
type Node struct {
|
||||
value interface{}
|
||||
prev *Node
|
||||
next *Node
|
||||
}
|
||||
|
||||
// CircularLinked 循环链表
|
||||
type CircularLinked struct {
|
||||
cursor *Node
|
||||
head *Node
|
||||
tail *Node
|
||||
size uint64
|
||||
}
|
||||
|
||||
// NewCircularLinked create a CircularLinked
|
||||
func NewCircularLinked(values ...interface{}) *CircularLinked {
|
||||
list := &CircularLinked{}
|
||||
if len(values) > 0 {
|
||||
list.Append(values...)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// Cursor get current Cursor
|
||||
func (list *CircularLinked) Cursor() *Node {
|
||||
if list.cursor == nil {
|
||||
list.cursor = list.head
|
||||
}
|
||||
return list.cursor
|
||||
}
|
||||
|
||||
// CursorNext get next Cursor
|
||||
func (list *CircularLinked) CursorNext() *Node {
|
||||
list.cursor = list.Cursor().next
|
||||
return list.cursor
|
||||
}
|
||||
|
||||
// CursorPrev get prev Cursor
|
||||
func (list *CircularLinked) CursorPrev() *Node {
|
||||
list.cursor = list.Cursor().prev
|
||||
return list.cursor
|
||||
}
|
||||
|
||||
// CursorToHead cursor move to head
|
||||
func (list *CircularLinked) CursorToHead() *Node {
|
||||
list.cursor = list.head
|
||||
return list.cursor
|
||||
}
|
||||
|
||||
// CursorToTail cursor move to tail
|
||||
func (list *CircularLinked) CursorToTail() *Node {
|
||||
list.cursor = list.tail
|
||||
return list.cursor
|
||||
}
|
||||
|
||||
// Append a value (one or more) at the end of the list (same as Append())
|
||||
func (list *CircularLinked) Append(values ...interface{}) {
|
||||
for _, value := range values {
|
||||
node := &Node{value: value}
|
||||
if list.size == 0 {
|
||||
list.head = node
|
||||
list.tail = node
|
||||
node.next = node
|
||||
node.prev = node
|
||||
} else {
|
||||
list.tail.next = node
|
||||
node.next = list.head
|
||||
node.prev = list.tail
|
||||
list.tail = node
|
||||
}
|
||||
list.size++
|
||||
}
|
||||
}
|
||||
|
||||
// Remove 移除一些节点
|
||||
func (list *CircularLinked) Remove(node *Node) {
|
||||
|
||||
switch list.size {
|
||||
case 0:
|
||||
list.errorNotInList(node)
|
||||
case 1:
|
||||
if list.head == node {
|
||||
list.head = nil
|
||||
list.tail = nil
|
||||
node.next = nil
|
||||
node.prev = nil
|
||||
list.cursor = nil
|
||||
list.size--
|
||||
} else {
|
||||
list.errorNotInList(node)
|
||||
}
|
||||
case 2:
|
||||
|
||||
node.prev = nil
|
||||
node.next = nil
|
||||
|
||||
switch node {
|
||||
case list.head:
|
||||
list.head = list.tail
|
||||
list.tail.prev = list.head
|
||||
list.head.next = list.tail
|
||||
list.cursor = list.head
|
||||
list.size--
|
||||
case list.tail:
|
||||
list.tail = list.head
|
||||
list.tail.prev = list.head
|
||||
list.head.next = list.tail
|
||||
list.cursor = list.head
|
||||
list.size--
|
||||
default:
|
||||
list.errorNotInList(node)
|
||||
}
|
||||
|
||||
default:
|
||||
switch node {
|
||||
case list.head:
|
||||
_, next := list.cutAndSplice(node)
|
||||
list.size--
|
||||
list.head = next
|
||||
if list.cursor == node {
|
||||
list.cursor = next
|
||||
}
|
||||
case list.tail:
|
||||
prev, _ := list.cutAndSplice(node)
|
||||
list.size--
|
||||
list.tail = prev
|
||||
if list.cursor == node {
|
||||
list.cursor = prev
|
||||
}
|
||||
default:
|
||||
_, next := list.cutAndSplice(node)
|
||||
list.size--
|
||||
if list.cursor == node {
|
||||
list.cursor = next
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// LookCursor for list show
|
||||
func (list *CircularLinked) LookCursor() string {
|
||||
cursor := list.Cursor()
|
||||
|
||||
content := "->["
|
||||
cur := list.head
|
||||
if list.size != 0 {
|
||||
for size := uint64(0); size < list.size; size++ {
|
||||
if cursor == cur {
|
||||
content += "(" + spew.Sprint(cur.value) + ")" + ", "
|
||||
} else {
|
||||
content += spew.Sprint(cur.value) + ", "
|
||||
}
|
||||
|
||||
cur = cur.next
|
||||
}
|
||||
}
|
||||
content = strings.TrimRight(content, ", ")
|
||||
showlen := len(content)
|
||||
if showlen >= 64 {
|
||||
showlen = 32
|
||||
}
|
||||
content += "]" + content[0:showlen] + " ..."
|
||||
return content
|
||||
}
|
||||
|
||||
// Clear for list show
|
||||
func (list *CircularLinked) Clear() {
|
||||
if list.size != 0 {
|
||||
list.head.prev = nil
|
||||
list.tail.next = nil
|
||||
list.head = nil
|
||||
list.tail = nil
|
||||
list.cursor = nil
|
||||
list.size = 0
|
||||
}
|
||||
}
|
||||
|
||||
// Size for list show
|
||||
func (list *CircularLinked) Size() uint64 {
|
||||
return list.size
|
||||
}
|
||||
|
||||
func (list *CircularLinked) errorNotInList(node *Node) {
|
||||
log.Println("the node value ", spew.Sprint(node), " is not in list")
|
||||
}
|
||||
|
||||
func (list *CircularLinked) cutAndSplice(node *Node) (prev, next *Node) {
|
||||
prev = node.prev
|
||||
next = node.next
|
||||
|
||||
prev.next = next
|
||||
|
||||
next.prev = prev
|
||||
|
||||
node.prev = nil
|
||||
node.next = nil
|
||||
|
||||
return prev, next
|
||||
}
|
67
structure_test.go
Normal file
67
structure_test.go
Normal file
|
@ -0,0 +1,67 @@
|
|||
package imitate
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCircularLinkedLookUp(t *testing.T) {
|
||||
|
||||
cl := NewCircularLinked(1, 2, 3, 4, 5, 6)
|
||||
if !(cl.head.value.(int) == 1 && cl.tail.value.(int) == 6) {
|
||||
t.Error(cl.LookCursor())
|
||||
}
|
||||
|
||||
cl = NewCircularLinked(6, 2, 3, 4, 5, 1)
|
||||
if !(cl.head.value.(int) == 6 && cl.tail.value.(int) == 1) {
|
||||
t.Error("New List is error:", cl.LookCursor())
|
||||
}
|
||||
|
||||
if cl.CursorNext().value.(int) != 2 {
|
||||
t.Error("CursorNext error:", cl.LookCursor())
|
||||
}
|
||||
|
||||
cl = NewCircularLinked(0, 1, 2, 3, 4, 5)
|
||||
for i := 0; i < 6; i++ {
|
||||
if cl.Cursor().value.(int) != i {
|
||||
t.Error("CursorNext error:", cl.LookCursor())
|
||||
}
|
||||
cl.CursorNext()
|
||||
}
|
||||
|
||||
for i := 0; i < 6; i++ {
|
||||
if cl.Cursor().value.(int) != i {
|
||||
t.Error("CursorNext loop error:", cl.LookCursor())
|
||||
}
|
||||
cl.CursorNext()
|
||||
}
|
||||
|
||||
cl = NewCircularLinked(6, 2, 3, 4, 5, 1)
|
||||
cl.Remove(cl.Cursor())
|
||||
if cl.Cursor().value != 2 {
|
||||
t.Error("Remove Head is error", cl.LookCursor())
|
||||
}
|
||||
cl.Remove(cl.CursorToTail())
|
||||
if cl.Cursor().value != 5 {
|
||||
t.Error("Remove CursorToTail is error", cl.LookCursor())
|
||||
}
|
||||
|
||||
cl.Remove(cl.CursorToHead())
|
||||
if cl.Cursor().value != 3 {
|
||||
t.Error("Remove CursorToHead is error", cl.LookCursor())
|
||||
}
|
||||
|
||||
limitCount := 0
|
||||
for cl.Size() > 0 {
|
||||
cl.Remove(cl.Cursor())
|
||||
limitCount++
|
||||
if limitCount >= 10 {
|
||||
t.Error("Not Clear", cl.LookCursor())
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
cl.Remove(cl.CursorToHead()) // nil is not in list is success!
|
||||
if cl.head != nil || cl.tail != nil || cl.cursor != nil {
|
||||
t.Error("Remove Boundary error")
|
||||
}
|
||||
}
|
|
@ -4,7 +4,8 @@ proxies : ["socks5://10.10.10.1:8080", "socks5://10.10.10.1:8082", "socks5://10.
|
|||
retry : 0
|
||||
priority : 10000
|
||||
|
||||
curl : "@test.curl"
|
||||
# curls: "@test.curl"
|
||||
curls : ["@test.curl", "curl 'https://segmentfault.com/a/1190000004850183' -H 'authority: segmentfault.com' -H 'cache-control: max-age=0' -H 'upgrade-insecure-requests: 1' -H 'user-agent: Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' -H 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8' -H 'accept-encoding: gzip, deflate, br' -H 'accept-language: zh' -H 'cookie: _ga=GA1.2.923011700.1533555581; PHPSESSID=web1~3uf1ijg2h8nctqdof7aa27g1p8; Hm_lvt_e23800c454aa573c0ccb16b52665ac26=1542945905,1542945911,1542967158,1542969075; Hm_lpvt_e23800c454aa573c0ccb16b52665ac26=1542969075' --compressed"]
|
||||
# next_do : "doothers"
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user