LCOV - code coverage report
Current view: top level - pebble/internal/treesteps - data.go (source / functions) Hit Total Coverage
Test: 2024-09-11 08:16Z e0afd551 - tests only.lcov Lines: 58 65 89.2 %
Date: 2024-09-11 08:16:49 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright 2024 The LevelDB-Go and Pebble Authors. All rights reserved. Use
       2             : // of this source code is governed by a BSD-style license that can be found in
       3             : // the LICENSE file.
       4             : 
       5             : package treesteps
       6             : 
       7             : import (
       8             :         "bytes"
       9             :         "compress/zlib"
      10             :         "encoding/base64"
      11             :         "encoding/json"
      12             :         "fmt"
      13             :         "net/url"
      14             :         "strings"
      15             : 
      16             :         "github.com/cockroachdb/pebble/internal/treeprinter"
      17             : )
      18             : 
      19             : // Steps contains the result of a recording: the full details of the hierarchy
      20             : // for each step.
      21             : type Steps struct {
      22             :         Name  string
      23             :         Steps []Step `json:"steps"`
      24             : }
      25             : 
      26             : // Step contains the tree for a single step in a recording.
      27             : type Step struct {
      28             :         Name string   `json:"name"`
      29             :         Root TreeNode `json:"tree"`
      30             : }
      31             : 
      32             : // TreeNode is a node in the tree for a step in a recording.
      33             : type TreeNode struct {
      34             :         Name       string      `json:"name"`
      35             :         Properties [][2]string `json:"props"`
      36             :         Ops        []string    `json:"ops"`
      37             :         Children   []TreeNode  `json:"children"`
      38             : }
      39             : 
      40             : // String returns the steps as a string (using treeprinter).
      41           1 : func (s Steps) String() string {
      42           1 :         var buf strings.Builder
      43           1 :         for step := range s.Steps {
      44           1 :                 if len(s.Steps) > 1 {
      45           1 :                         fmt.Fprintf(&buf, "step %d/%d:\n", step+1, len(s.Steps))
      46           1 :                 }
      47           1 :                 out := s.Steps[step].Root.String()
      48           1 :                 if len(s.Steps) > 1 {
      49           1 :                         for _, l := range strings.Split(strings.TrimSpace(out), "\n") {
      50           1 :                                 fmt.Fprintf(&buf, "  %s\n", l)
      51           1 :                         }
      52           0 :                 } else {
      53           0 :                         buf.WriteString(out)
      54           0 :                 }
      55             :         }
      56           1 :         return buf.String()
      57             : }
      58             : 
      59           1 : func (t *TreeNode) String() string {
      60           1 :         tp := treeprinter.New()
      61           1 :         t.print(tp)
      62           1 :         return tp.String()
      63           1 : }
      64             : 
      65           1 : func (t *TreeNode) print(parent treeprinter.Node) {
      66           1 :         name := t.Name
      67           1 :         for i := range t.Ops {
      68           1 :                 name += fmt.Sprintf("  ← %s", t.Ops[i])
      69           1 :         }
      70           1 :         n := parent.Child(name)
      71           1 :         for _, p := range t.Properties {
      72           1 :                 n.Childf("%s: %s", p[0], p[1])
      73           1 :         }
      74           1 :         for i := range t.Children {
      75           1 :                 t.Children[i].print(n)
      76           1 :         }
      77             : }
      78             : 
      79             : // URL for a visualization of the steps. The URL contains the encoded and
      80             : // compressed data as the URL fragment.
      81           1 : func (s Steps) URL() url.URL {
      82           1 :         // TODO(radu): ideally we would encode Steps and have a graphical
      83           1 :         // visualization. For now, we generate and encode the ASCII trees.
      84           1 :         var output struct {
      85           1 :                 Name      string
      86           1 :                 StepNames []string
      87           1 :                 Steps     []string
      88           1 :         }
      89           1 :         output.Name = s.Name
      90           1 :         output.StepNames = make([]string, len(s.Steps))
      91           1 :         output.Steps = make([]string, len(s.Steps))
      92           1 :         for i := range s.Steps {
      93           1 :                 output.StepNames[i] = s.Steps[i].Name
      94           1 :                 output.Steps[i] = s.Steps[i].Root.String()
      95           1 :         }
      96             : 
      97           1 :         var jsonBuf bytes.Buffer
      98           1 :         if err := json.NewEncoder(&jsonBuf).Encode(&output); err != nil {
      99           0 :                 panic(err)
     100             :         }
     101           1 :         var compressed bytes.Buffer
     102           1 :         encoder := base64.NewEncoder(base64.URLEncoding, &compressed)
     103           1 :         compressor := zlib.NewWriter(encoder)
     104           1 :         if _, err := jsonBuf.WriteTo(compressor); err != nil {
     105           0 :                 panic(err)
     106             :         }
     107           1 :         if err := compressor.Close(); err != nil {
     108           0 :                 panic(err)
     109             :         }
     110           1 :         if err := encoder.Close(); err != nil {
     111           0 :                 panic(err)
     112             :         }
     113           1 :         return url.URL{
     114           1 :                 Scheme:   "https",
     115           1 :                 Host:     "raduberinde.github.io",
     116           1 :                 Path:     "treesteps/decode.html",
     117           1 :                 Fragment: compressed.String(),
     118           1 :         }
     119             : }

Generated by: LCOV version 1.14