Skip to content
This repository has been archived by the owner on Sep 15, 2020. It is now read-only.

Commit

Permalink
Merge pull request #646 from holochain/643-add-index-for-dump
Browse files Browse the repository at this point in the history
643 add index for dump, closes #643
  • Loading branch information
clarenceb committed May 2, 2018
2 parents 6675569 + 51fb0a8 commit a17510b
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 20 deletions.
15 changes: 10 additions & 5 deletions chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -564,11 +564,16 @@ func (c *Chain) Validate(skipEntries bool) (err error) {

// String converts a chain to a textual dump of the headers and entries
func (c *Chain) String() string {
return c.Dump(0)
}

// Dump converts a chain to a textual dump of the headers and entries from a starting index
func (c *Chain) Dump(start int) string {
c.lk.RLock()
defer c.lk.RUnlock()
l := len(c.Headers)
r := ""
for i := 0; i < l; i++ {
for i := start; i < l; i++ {
hdr := c.Headers[i]
hash := c.Hashes[i]
r += fmt.Sprintf("%s:%s @ %v\n", hdr.Type, hash, hdr.Time)
Expand All @@ -593,7 +598,7 @@ func (c *Chain) String() string {
}

// JSON converts a chain to a json string dump of the headers and entries
func (c *Chain) JSON() (string, error) {
func (c *Chain) JSON(start int) (string, error) {
c.lk.RLock()
defer c.lk.RUnlock()
l := len(c.Headers)
Expand All @@ -604,7 +609,7 @@ func (c *Chain) JSON() (string, error) {

buffer.WriteString("{")

for i := 0; i < l; i++ {
for i := start; i < l; i++ {
hdr := c.Headers[i]
hash := c.Hashes[i]

Expand Down Expand Up @@ -639,7 +644,7 @@ func (c *Chain) JSON() (string, error) {
}

// Dot converts a chain to a GraphViz 'dot' format dump of the headers and entries
func (c *Chain) Dot() (dump string, err error) {
func (c *Chain) Dot(start int) (dump string, err error) {
c.lk.RLock()
defer c.lk.RUnlock()
l := len(c.Headers)
Expand All @@ -651,7 +656,7 @@ func (c *Chain) Dot() (dump string, err error) {
buffer.WriteString(`node [shape=record fontname="Arial",fontsize="10",style="rounded, filled",penwidth=2,fontcolor="#c5c5c5",color="#8d00ff",fillcolor="#181818"];` + "\n")
buffer.WriteString(`edge [penwidth=2, color="#8d00ff"];` + "\n")

for i := 0; i < l; i++ {
for i := start; i < l; i++ {
hdr := c.Headers[i]
hash := c.Hashes[i]
headerLabel := ""
Expand Down
55 changes: 47 additions & 8 deletions chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ func TestChain2JSON(t *testing.T) {
c := NewChain(hashSpec)

Convey("it should dump empty JSON object for empty chain", t, func() {
json, err := c.JSON()
json, err := c.JSON(0)
So(err, ShouldBeNil)
So(json, ShouldEqual, "{}")
})
Expand All @@ -444,7 +444,7 @@ func TestChain2JSON(t *testing.T) {
c.AddEntry(now, DNAEntryType, &e, key)

Convey("it should dump a DNA entry as JSON", t, func() {
json, err := c.JSON()
json, err := c.JSON(0)
So(err, ShouldBeNil)
json = NormaliseJSON(json)
matched, err := regexp.MatchString(`{"%dna":{"header":{.*},"content":"dna entry"}}`, json)
Expand All @@ -456,7 +456,7 @@ func TestChain2JSON(t *testing.T) {
c.AddEntry(now, AgentEntryType, &e, key)

Convey("it should dump a Agent entry as JSON", t, func() {
json, err := c.JSON()
json, err := c.JSON(0)
So(err, ShouldBeNil)
json = NormaliseJSON(json)
matched, err := regexp.MatchString(`{"%dna":{"header":{.*},"content":"dna entry"},"%agent":{"header":{.*},"content":"agent entry"}}`, json)
Expand All @@ -468,21 +468,34 @@ func TestChain2JSON(t *testing.T) {
c.AddEntry(now, "handle", &e, key)

Convey("it should dump chain with entries as JSON", t, func() {
json, err := c.JSON()
json, err := c.JSON(0)
So(err, ShouldBeNil)
json = NormaliseJSON(json)
matched, err := regexp.MatchString(`{"%dna":{.*},"%agent":{.*},"entries":\[{"header":{"type":"handle",.*"},"content":"chain entry"}\]}`, json)
So(err, ShouldBeNil)
So(matched, ShouldBeTrue)
})

e.C = "chain entry 2"
c.AddEntry(now, "handle", &e, key)
e.C = "chain entry 3"
c.AddEntry(now, "handle", &e, key)
Convey("it should dump chain from the given start index", t, func() {
json, err := c.JSON(2)
So(err, ShouldBeNil)
json = NormaliseJSON(json)
matched, err := regexp.MatchString(`{"entries":\[{"header":{"type":"handle",.*"},"content":"chain entry 2"},{"header":{"type":"handle",.*"},"content":"chain entry 3"}\]}`, json)
So(err, ShouldBeNil)
So(matched, ShouldBeTrue)
})
}

func TestChain2Dot(t *testing.T) {
hashSpec, key, now := chainTestSetup()
c := NewChain(hashSpec)

Convey("it should dump an empty 'dot' document for empty chain", t, func() {
dot, err := c.Dot()
dot, err := c.Dot(0)
So(err, ShouldBeNil)
matched, err := regexp.MatchString(`digraph chain {.*}`, strings.Replace(dot, "\n", "", -1))
So(err, ShouldBeNil)
Expand All @@ -495,7 +508,7 @@ func TestChain2Dot(t *testing.T) {
c.AddEntry(now, DNAEntryType, &e, key)

Convey("after adding the dna, the dump should include the genesis entry in 'dot' format", t, func() {
dot, err := c.Dot()
dot, err := c.Dot(0)
So(err, ShouldBeNil)

hdr := c.Headers[0]
Expand Down Expand Up @@ -524,7 +537,7 @@ header0->content0;`
c.AddEntry(now, AgentEntryType, &e, key)

Convey("after adding the agent, the dump should include the agent entry in 'dot' format", t, func() {
dot, err := c.Dot()
dot, err := c.Dot(0)
So(err, ShouldBeNil)

hdr0 := c.Headers[0]
Expand Down Expand Up @@ -572,7 +585,7 @@ header1->content1;`
c.AddEntry(now, "handle", &e, key)

Convey("after adding an entry, the dump should include the entry in 'dot' format", t, func() {
dot, err := c.Dot()
dot, err := c.Dot(0)
So(err, ShouldBeNil)

hdr0 := c.Headers[0]
Expand Down Expand Up @@ -630,6 +643,32 @@ header2 [label=<{HEADER 2|
{Entry|` + hdrEntry2 + `}
}>];
content2 [label=<{ENTRY 2|\{"Links":[<br/>\{"Base":"ABC",<br/>"Link":"XYZ",<br/>"Tag":"handle"\}]\}}>];
header2->content2;`

So(dot, ShouldContainSubstring, expectedDot)
})

Convey("only entries starting from the specified index should be dumped", t, func() {
dot, err := c.Dot(2)
So(err, ShouldBeNil)

hdr2 := c.Headers[2]
timestamp2 := fmt.Sprintf("%v", hdr2.Time)
hdrType2 := fmt.Sprintf("%v", hdr2.Type)
hdrEntry2 := fmt.Sprintf("%v", hdr2.EntryLink)
nextHeader2 := fmt.Sprintf("%v", hdr2.HeaderLink)
next2 := fmt.Sprintf("%s: %v", hdr2.Type, hdr2.TypeLink)
hash2 := fmt.Sprintf("%s", c.Hashes[2])

expectedDot := `header2 [label=<{HEADER 2|
{Type|` + hdrType2 + `}|
{Hash|` + hash2 + `}|
{Timestamp|` + timestamp2 + `}|
{Next Header|` + nextHeader2 + `}|
{Next|` + next2 + `}|
{Entry|` + hdrEntry2 + `}
}>];
content2 [label=<{ENTRY 2|\{"Links":[<br/>\{"Base":"ABC",<br/>"Link":"XYZ",<br/>"Tag":"handle"\}]\}}>];
header2->content2;`

So(dot, ShouldContainSubstring, expectedDot)
Expand Down
10 changes: 8 additions & 2 deletions cmd/hcadmin/hcadmin.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ func setupApp() (app *cli.App) {
var root string
var service *holo.Service
var bridgeCalleeAppData, bridgeCallerAppData string
var start int

app.Flags = []cli.Flag{
cli.BoolFlag{
Expand Down Expand Up @@ -91,6 +92,11 @@ func setupApp() (app *cli.App) {
Destination: &json,
Usage: "Dump chain or dht as JSON string",
},
cli.IntFlag{
Name: "index",
Destination: &start,
Usage: "starting index for dump (zero based)",
},
},
Action: func(c *cli.Context) error {
h, err := cmd.GetHolochain(c.Args().First(), service, "dump")
Expand All @@ -104,10 +110,10 @@ func setupApp() (app *cli.App) {
dnaHash := h.DNAHash()
if dumpChain {
if json {
dump, _ := h.Chain().JSON()
dump, _ := h.Chain().JSON(start)
fmt.Println(dump)
} else {
fmt.Printf("Chain for: %s\n%v", dnaHash, h.Chain())
fmt.Printf("Chain for: %s\n%v", dnaHash, h.Chain().Dump(start))
}
}
if dumpDHT {
Expand Down
16 changes: 11 additions & 5 deletions cmd/hcdev/hcdev.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ func setupApp() (app *cli.App) {

var dumpScenario string
var dumpTest bool
var start int

var bridgeAppTmpFilePath string

Expand Down Expand Up @@ -806,6 +807,11 @@ func setupApp() (app *cli.App) {
Destination: &json,
Usage: "Dump chain or dht as JSON string",
},
cli.IntFlag{
Name: "index",
Destination: &start,
Usage: "starting index for dump (zero based)",
},
cli.BoolFlag{
Name: "test",
Destination: &dumpTest,
Expand Down Expand Up @@ -860,23 +866,23 @@ func setupApp() (app *cli.App) {
dnaHash := h.DNAHash()
if dumpChain {
if json {
dump, _ := h.Chain().JSON()
dump, _ := h.Chain().JSON(start)
fmt.Println(dump)
} else if dumpFormat != "" {
switch dumpFormat {
case "string":
fmt.Printf("Chain for: %s\n%v", dnaHash, h.Chain())
fmt.Printf("Chain for: %s\n%v", dnaHash, h.Chain().Dump(start))
case "dot":
dump, _ := h.Chain().Dot()
dump, _ := h.Chain().Dot(start)
fmt.Println(dump)
case "json":
dump, _ := h.Chain().JSON()
dump, _ := h.Chain().JSON(start)
fmt.Println(dump)
default:
return cmd.MakeErr(c, "format must be one of dot,json,string")
}
} else {
fmt.Printf("Chain for: %s\n%v", dnaHash, h.Chain())
fmt.Printf("Chain for: %s\n%v", dnaHash, h.Chain().Dump(start))
}
}
if dumpDHT {
Expand Down

0 comments on commit a17510b

Please sign in to comment.