Skip to content

Commit

Permalink
Use only one line per message, removing redundant visiblity of tester…
Browse files Browse the repository at this point in the history
… between client and server
  • Loading branch information
mAdkins committed May 16, 2023
1 parent 889d3a9 commit e5ab6e5
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 53 deletions.
86 changes: 50 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,21 +124,19 @@ In this case a blank line will be emitted to separate the new messages from the

Specific conventions used in all output formats:

| Example | Definition |
|---------------------|------------------------------------------------|
| `!=tester-->server` | Direction of message [^1] |
| `#size=125` | Size of content from message header |

[^1]: In Nexus mode there will be two log items for each message.
The first will be from the client or server to the tester,
the second will be from the tester to the server or client as appropriate
| Example | Definition |
|---------------------|-------------------------------------|
| `!=client-->server` | Direction of message |
| `#size=125` | Size of content from message header |

In all formats but `json` these will be at the left of every line
after the timestamp, log level, and message text.
In `json` mode these fields will still be present but not as easy to find.

The message direction is configured so that the `client`, when present, is on the left and
the `server`, when present, is on the right.
If either the client or the server is absent any messages will replace the missing
entity with `tester`, representing `lsp-tester` itself.

In the examples below the use of `logFormat=<format>` always imply
the same behavior for log files by using `fileFormat=<format>`.
Expand Down Expand Up @@ -225,21 +223,21 @@ in which the previous log data would show as:
This mode attempts to pull out key fields and only show small blocks of meaningful data.
Specific conventions used in this format:

| Example | Definition |
|---------------------|------------------------------------------------|
| `$Type=request` | Type of message [^2] |
| `%ID=81` | Message ID |
| `%method=$/alive/eval` | Method for request |
| `<text="(+ 2 (/ 15 5))` | Parameter with name prefixed by `<` |
| `>text=5` | Result item with name prefixed by `>` |
| `<>method=$/alive/eval` | Method from request provided with response [^3] |
| `<>text="(+ 2 (/ 15 5))"` | Parameter from request provided with response [^3] |

[^2]: The `$Type` of message is derived from the available fields.
| Example | Definition |
|---------------------------|----------------------------------------------------|
| `$Type=request` | Type of message [^1] |
| `%ID=81` | Message ID |
| `%method=$/alive/eval` | Method for request |
| `<text="(+ 2 (/ 15 5))` | Parameter with name prefixed by `<` |
| `>text=5` | Result item with name prefixed by `>` |
| `<>method=$/alive/eval` | Method from request provided with response [^2] |
| `<>text="(+ 2 (/ 15 5))"` | Parameter from request provided with response [^2] |

[^1]: The `$Type` of message is derived from the available fields.
There is no specific "type" field in the Language Server Protocol
so this derivation is somewhat fuzzy and may be wrong sometimes.

[^3]: Method and parameter data from requests is stored by ID,
[^2]: Method and parameter data from requests is stored by ID,
looked up when a response message is found with the same ID, and
added to the log entry for the response using the `<>` prefix.
This data is not actually in the response message.
Expand Down Expand Up @@ -386,20 +384,21 @@ This scenario handles two problems:

## Command Line Flags

| Flag | Type | Description |
|---------------|----------|-----------------------------------------------------|
| `-host` | `string` | LSP server host address (default `"127.0.0.1"`) |
| `-clientPort` | `uint` | Port number served for extension client to contact |
| `-serverPort` | `uint` | Port number on which to contact LSP server |
| `-webPort` | `uint` | Port for web server for interactive control |
| `-logLevel` | `string` | Set the log level (see below |
| `-logFormat` | `string` | Format value for console output (see below) |
| `-logFile` | `string` | Log file path (default no log file) |
| `-fileAppend` | `bool` | Append to any pre-existing log file |
| `-fileFormat` | `string` | Format value for log file (see below) |
| `-request` | `string` | Path to file to be sent when connected (client mode) |
| `-messages` | `string` | Path to directory of message files (for Web server) |
| `-help` | `bool` | Show usage and flags |
| Flag | Type | Description |
|-----------------|----------|------------------------------------------------------|
| `-host` | `string` | LSP server host address (default `"127.0.0.1"`) |
| `-clientPort` | `uint` | Port number served for extension client to contact |
| `-serverPort` | `uint` | Port number on which to contact LSP server |
| `-webPort` | `uint` | Port for web server for interactive control |
| `-logLevel` | `string` | Set the log level (see below |
| `-logFormat` | `string` | Format value for console output (see below) |
| `-logMsgTwice` | `bool` | Show each message twice with `tester` in the middle. |
| `-logFile` | `string` | Log file path (default no log file) |
| `-fileAppend` | `bool` | Append to any pre-existing log file |
| `-fileFormat` | `string` | Format value for log file (see below) |
| `-request` | `string` | Path to file to be sent when connected (client mode) |
| `-messages` | `string` | Path to directory of message files (for Web server) |
| `-help` | `bool` | Show usage and flags |

Boolean flags (e.g. `-fileAppend` and `-help`) do not require a value.
The presence of such a flag indicates a value of `true`.
Expand Down Expand Up @@ -429,6 +428,21 @@ Choices are specified in the following table.
Each value includes itself and all messages above it in the table.
The default value is `info`.

The `logMsgTwice` flag converts
```
17:29:31 INF Send !=client-1-->server #size=122 $Type=request %ID=8 %method=$/alive/eval <package=cl-user <storeResult=true <text="(+ 2 (/ 15 5))"
17:29:31 INF Send !=client-1<--server #size=46 $Type=response %ID=8 <>method=$/alive/eval <>package=cl-user <>storeResult=true <>text="(+ 2 (/ 15 5))" >text=5
```
to
```
17:36:34 INF Rcvd !=client-1-->tester #size=122 $Type=request %ID=8 %method=$/alive/eval <package=cl-user <storeResult=true <text="(+ 2 (/ 15 5))"
17:36:34 INF Send !=tester-->server #size=122 $Type=request %ID=8 %method=$/alive/eval <package=cl-user <storeResult=true <text="(+ 2 (/ 15 5))"
17:36:34 INF Rcvd !=tester<--server #size=46 $Type=response %ID=8 <>method=$/alive/eval <>package=cl-user <>storeResult=true <>text="(+ 2 (/ 15 5))" >text=5
17:36:34 INF Send !=client-1<--tester #size=46 $Type=response %ID=8 <>method=$/alive/eval <>package=cl-user <>storeResult=true <>text="(+ 2 (/ 15 5))" >text=5
```
to show the role of `lsp-tester` in passing messages back and forth.
This may not be very useful except when demonstrating that `lsp-tester` is not functional.

## Development Notes

This application started as a simple one file project and
Expand All @@ -440,12 +454,12 @@ Feel free to fork the code and rewrite it if you desire.
Please don't send any massive refactoring PRs, no matter how tempting.
PRs with small changes may be welcome if the author has the time and is in the mood
(just like most other open source applications).
Remember, [time is fleeting](https://www.youtube.com/watch?v=umj0gu5nEGs)[^4] and
Remember, [time is fleeting](https://www.youtube.com/watch?v=umj0gu5nEGs)[^3] and
we all have other stuff to do. ;-)

Thanks for listening.

[^4]: It turns out the "pelvic thrust"
[^3]: It turns out the "pelvic thrust"
(as in the dance, no double entendre intended here)
is a good way to unkink one's back after
leaning forward in one's chair for hours peering into a computer screen. ;-)
4 changes: 0 additions & 4 deletions notes.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
* Working on refactoring
+ flags and logging pulled out
! simple server eval finds request method and params,
nexus mode doesn't seem to
* Continue to pull fields out of messages on simple-messages branch
- (even though they're now keyword messages)
- e.g. textDocument
Expand Down
6 changes: 6 additions & 0 deletions tester/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type Set struct {
logFileAppend bool
logFileFormat string
logStdFormat string
logMsgTwice bool
}

func NewSet() *Set {
Expand All @@ -46,6 +47,7 @@ func NewSet() *Set {
set.BoolVar(&set.logFileAppend, "fileAppend", false, "Append to any pre-existing log file")
set.StringVar(&set.logFileFormat, "fileFormat", logging.FmtDefault, "Log file format")
set.UintVar(&set.maxFieldLen, "maxFieldLen", 32, "Maximum length of fields to display")
set.BoolVar(&set.logMsgTwice, "logMsgTwice", false, "Log each message twice with tester in the middle")
return set
}

Expand Down Expand Up @@ -184,3 +186,7 @@ func (s *Set) MessageDir() string {
func (s *Set) RequestPath() string {
return s.requestPath
}

func (s *Set) LogMessageTwice() bool {
return s.logMsgTwice
}
4 changes: 2 additions & 2 deletions tester/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func main() {
return
}

client = network.NewReceiver("server", connection, msgLogger, &waiter)
client = network.NewReceiver("server", flagSet, connection, msgLogger, &waiter)
if err = client.Start(); err != nil {
log.Error().Err(err).Msg("Unable to start Receiver")
return
Expand All @@ -70,7 +70,7 @@ func main() {
} else {
go listener.ListenForClient(func(conn net.Conn) {
log.Info().Msg("Accepting client")
server = network.NewReceiver("client", conn, msgLogger, &waiter)
server = network.NewReceiver("client", flagSet, conn, msgLogger, &waiter)
if err = server.Start(); err != nil {
log.Error().Err(err).Msg("Unable to start Receiver")
return
Expand Down
6 changes: 3 additions & 3 deletions tester/message/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,16 @@ func SendMessage(to string, message data.AnyMap, connection net.Conn, msgLgr *Lo

if content, err := json.Marshal(message); err != nil {
return fmt.Errorf("marshal request: %w", err)
} else if err := SendContent(to, content, connection, msgLgr); err != nil {
} else if err := SendContent("tester", to, content, connection, msgLgr); err != nil {
return fmt.Errorf("send content: %w", err)
}
return nil
}

// SendContent sends byte array content to the specified connection.
// A message header is provided before the content.
func SendContent(to string, content []byte, connection net.Conn, msgLgr *Logger) error {
msgLgr.Message("tester", to, "Send", content)
func SendContent(from, to string, content []byte, connection net.Conn, msgLgr *Logger) error {
msgLgr.Message(from, to, "Send", content)
message := fmt.Sprintf(msgHeaderFormat, len(content), string(content))
if _, err := connection.Write([]byte(message)); err != nil {
return fmt.Errorf("write content: %w", err)
Expand Down
25 changes: 17 additions & 8 deletions tester/network/receiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

"github.com/madkins23/go-utils/log"

"github.com/madkins23/lsp-tester/tester/flags"
"github.com/madkins23/lsp-tester/tester/message"
)

Expand All @@ -38,18 +39,20 @@ func Receivers() map[string]*Receiver {
}

type Receiver struct {
flags *flags.Set
to string
conn net.Conn
other *Receiver
msgLgr *message.Logger
waiter *sync.WaitGroup
}

func NewReceiver(to string, connection net.Conn, msgLgr *message.Logger, waiter *sync.WaitGroup) *Receiver {
func NewReceiver(to string, flags *flags.Set, connection net.Conn, msgLgr *message.Logger, waiter *sync.WaitGroup) *Receiver {
if to == "client" {
to += "-" + strconv.Itoa(int(sequence.Add(1)))
}
return &Receiver{
flags: flags,
to: to,
conn: connection,
msgLgr: msgLgr,
Expand Down Expand Up @@ -135,20 +138,26 @@ func (r *Receiver) Receive(ready *chan bool) {
log.Error().Msgf("Read %d bytes instead of %d", length, contentLen)
} else {
content = content[:contentLen]
r.msgLgr.Message(r.to, "tester", "Rcvd", content)
// TODO: What if there are multiple clients?
// How do we know which one server should send to?
if r.other != nil {
if err := r.other.sendContent(content); err != nil {
if r.other == nil {
r.msgLgr.Message(r.to, "tester", "Rcvd", content)
} else {
// TODO: What if there are multiple clients?
// How do we know which one server should send to?
from := r.to
if r.flags.LogMessageTwice() {
from = "tester"
r.msgLgr.Message(r.to, "tester", "Rcvd", content)
}
if err := r.other.sendContent(from, content); err != nil {
log.Error().Err(err).Msg("Sending outgoing message")
}
}
}
}
}

func (r *Receiver) sendContent(content []byte) error {
if err := message.SendContent(r.to, content, r.conn, r.msgLgr); err != nil {
func (r *Receiver) sendContent(from string, content []byte) error {
if err := message.SendContent(from, r.to, content, r.conn, r.msgLgr); err != nil {
return fmt.Errorf("send content: %w", err)
} else {
return nil
Expand Down

0 comments on commit e5ab6e5

Please sign in to comment.