mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-03-05 20:49:04 -08:00
feat(wifi): read wifi state using native methods
This commit is contained in:
parent
393f99da93
commit
ce04362bb4
|
@ -21,24 +21,22 @@ Currently only supports Windows and WSL. Pull requests for Darwin and Linux supp
|
||||||
"background": "#8822ee",
|
"background": "#8822ee",
|
||||||
"foreground": "#222222",
|
"foreground": "#222222",
|
||||||
"background_templates": [
|
"background_templates": [
|
||||||
"{{ if (not .Connected) }}#FF1111{{ end }}",
|
|
||||||
"{{ if (lt .Signal 60) }}#DDDD11{{ else if (lt .Signal 90) }}#DD6611{{ else }}#11CC11{{ end }}"
|
"{{ if (lt .Signal 60) }}#DDDD11{{ else if (lt .Signal 90) }}#DD6611{{ else }}#11CC11{{ end }}"
|
||||||
],
|
],
|
||||||
"powerline_symbol": "\uE0B0",
|
"powerline_symbol": "\uE0B0",
|
||||||
"properties": {
|
"properties": {
|
||||||
"template": "{{ if .Connected }}\uFAA8{{ else }}\uFAA9{{ end }} {{ if .Connected }}{{ .SSID }} {{ .Signal }}% {{ .ReceiveRate }}Mbps{{ else }}{{ .State }}{{ end }}"
|
"template": "\uFAA8 {{ .SSID }} {{ .Signal }}% {{ .ReceiveRate }}Mbps"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Properties
|
## Properties
|
||||||
|
|
||||||
- template: `string` - A go [text/template][go-text-template] extended with [sprig][sprig] using the properties below
|
- template: `string` - A go [text/template][go-text-template] extended with [sprig][sprig] using the properties below.
|
||||||
|
Defaults to `{{ if .Error }}{{ .Error }}{{ else }}\uFAA8 {{ .SSID }} {{ .Signal }}% {{ .ReceiveRate }}Mbps{{ end }}`
|
||||||
|
|
||||||
## Template Properties
|
## Template Properties
|
||||||
|
|
||||||
- `.Connected`: `bool` - if WiFi is currently connected
|
|
||||||
- `.State`: `string` - WiFi connection status - _e.g. connected or disconnected_
|
|
||||||
- `.SSID`: `string` - the SSID of the current wifi network
|
- `.SSID`: `string` - the SSID of the current wifi network
|
||||||
- `.RadioType`: `string` - the radio type - _e.g. 802.11ac, 802.11ax, 802.11n, etc._
|
- `.RadioType`: `string` - the radio type - _e.g. 802.11ac, 802.11ax, 802.11n, etc._
|
||||||
- `.Authentication`: `string` - the authentication type - _e.g. WPA2-Personal, WPA2-Enterprise, etc._
|
- `.Authentication`: `string` - the authentication type - _e.g. WPA2-Personal, WPA2-Enterprise, etc._
|
||||||
|
|
33
src/constants_windows.go
Normal file
33
src/constants_windows.go
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
const (
|
||||||
|
FHSS WifiType = "FHSS"
|
||||||
|
DSSS WifiType = "DSSS"
|
||||||
|
IR WifiType = "IR"
|
||||||
|
A WifiType = "802.11a"
|
||||||
|
HRDSSS WifiType = "HRDSSS"
|
||||||
|
G WifiType = "802.11g"
|
||||||
|
N WifiType = "802.11n"
|
||||||
|
AC WifiType = "802.11ac"
|
||||||
|
|
||||||
|
Infrastructure WifiType = "Infrastructure"
|
||||||
|
Independent WifiType = "Independent"
|
||||||
|
Any WifiType = "Any"
|
||||||
|
|
||||||
|
OpenSystem WifiType = "802.11 Open System"
|
||||||
|
SharedKey WifiType = "802.11 Shared Key"
|
||||||
|
WPA WifiType = "WPA"
|
||||||
|
WPAPSK WifiType = "WPA PSK"
|
||||||
|
WPANone WifiType = "WPA NONE"
|
||||||
|
WPA2 WifiType = "WPA2"
|
||||||
|
WPA2PSK WifiType = "WPA2 PSK"
|
||||||
|
Disabled WifiType = "disabled"
|
||||||
|
Unknown WifiType = "Unknown"
|
||||||
|
|
||||||
|
None WifiType = "None"
|
||||||
|
WEP40 WifiType = "WEP40"
|
||||||
|
TKIP WifiType = "TKIP"
|
||||||
|
CCMP WifiType = "CCMP"
|
||||||
|
WEP104 WifiType = "WEP104"
|
||||||
|
WEP WifiType = "WEP"
|
||||||
|
)
|
|
@ -72,6 +72,22 @@ type windowsRegistryValue struct {
|
||||||
str string
|
str string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WifiType string
|
||||||
|
|
||||||
|
type wifiInfo struct {
|
||||||
|
SSID string
|
||||||
|
Interface string
|
||||||
|
RadioType WifiType
|
||||||
|
PhysType WifiType
|
||||||
|
Authentication WifiType
|
||||||
|
Cipher WifiType
|
||||||
|
Channel int
|
||||||
|
ReceiveRate int
|
||||||
|
TransmitRate int
|
||||||
|
Signal int
|
||||||
|
Error string
|
||||||
|
}
|
||||||
|
|
||||||
type environmentInfo interface {
|
type environmentInfo interface {
|
||||||
getenv(key string) string
|
getenv(key string) string
|
||||||
getcwd() string
|
getcwd() string
|
||||||
|
@ -110,6 +126,7 @@ type environmentInfo interface {
|
||||||
inWSLSharedDrive() bool
|
inWSLSharedDrive() bool
|
||||||
convertToLinuxPath(path string) string
|
convertToLinuxPath(path string) string
|
||||||
convertToWindowsPath(path string) string
|
convertToWindowsPath(path string) string
|
||||||
|
getWifiNetwork() (*wifiInfo, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type commandCache struct {
|
type commandCache struct {
|
||||||
|
|
|
@ -93,3 +93,7 @@ func (env *environment) convertToLinuxPath(path string) string {
|
||||||
}
|
}
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (env *environment) getWifiNetwork() (*wifiInfo, error) {
|
||||||
|
return nil, errors.New("not implemented")
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode/utf16"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/Azure/go-ansiterm/winterm"
|
"github.com/Azure/go-ansiterm/winterm"
|
||||||
|
@ -260,3 +261,214 @@ func (env *environment) convertToWindowsPath(path string) string {
|
||||||
func (env *environment) convertToLinuxPath(path string) string {
|
func (env *environment) convertToLinuxPath(path string) string {
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
hapi = syscall.NewLazyDLL("wlanapi.dll")
|
||||||
|
hWlanOpenHandle = hapi.NewProc("WlanOpenHandle")
|
||||||
|
hWlanCloseHandle = hapi.NewProc("WlanCloseHandle")
|
||||||
|
hWlanEnumInterfaces = hapi.NewProc("WlanEnumInterfaces")
|
||||||
|
hWlanQueryInterface = hapi.NewProc("WlanQueryInterface")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (env *environment) getWifiNetwork() (*wifiInfo, error) {
|
||||||
|
env.trace(time.Now(), "getWifiNetwork")
|
||||||
|
// Open handle
|
||||||
|
var pdwNegotiatedVersion uint32
|
||||||
|
var phClientHandle uint32
|
||||||
|
e, _, err := hWlanOpenHandle.Call(uintptr(uint32(2)), uintptr(unsafe.Pointer(nil)), uintptr(unsafe.Pointer(&pdwNegotiatedVersion)), uintptr(unsafe.Pointer(&phClientHandle)))
|
||||||
|
if e != 0 {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// defer closing handle
|
||||||
|
defer func() {
|
||||||
|
_, _, _ = hWlanCloseHandle.Call(uintptr(phClientHandle), uintptr(unsafe.Pointer(nil)))
|
||||||
|
}()
|
||||||
|
|
||||||
|
// list interfaces
|
||||||
|
var interfaceList *WLAN_INTERFACE_INFO_LIST
|
||||||
|
e, _, err = hWlanEnumInterfaces.Call(uintptr(phClientHandle), uintptr(unsafe.Pointer(nil)), uintptr(unsafe.Pointer(&interfaceList)))
|
||||||
|
if e != 0 {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// use first interface that is connected
|
||||||
|
numberOfInterfaces := int(interfaceList.dwNumberOfItems)
|
||||||
|
infoSize := unsafe.Sizeof(interfaceList.InterfaceInfo[0])
|
||||||
|
for i := 0; i < numberOfInterfaces; i++ {
|
||||||
|
network := (*WLAN_INTERFACE_INFO)(unsafe.Pointer(uintptr(unsafe.Pointer(&interfaceList.InterfaceInfo[0])) + uintptr(i)*infoSize))
|
||||||
|
if network.isState != 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return env.parseNetworkInterface(network, phClientHandle)
|
||||||
|
}
|
||||||
|
return nil, errors.New("Not connected")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *environment) parseNetworkInterface(network *WLAN_INTERFACE_INFO, clientHandle uint32) (*wifiInfo, error) {
|
||||||
|
info := wifiInfo{}
|
||||||
|
info.Interface = strings.TrimRight(string(utf16.Decode(network.strInterfaceDescription[:])), "\x00")
|
||||||
|
|
||||||
|
// Query wifi connection state
|
||||||
|
var dataSize uint16
|
||||||
|
var wlanAttr *WLAN_CONNECTION_ATTRIBUTES
|
||||||
|
e, _, err := hWlanQueryInterface.Call(uintptr(clientHandle),
|
||||||
|
uintptr(unsafe.Pointer(&network.InterfaceGuid)),
|
||||||
|
uintptr(7), // wlan_intf_opcode_current_connection
|
||||||
|
uintptr(unsafe.Pointer(nil)),
|
||||||
|
uintptr(unsafe.Pointer(&dataSize)),
|
||||||
|
uintptr(unsafe.Pointer(&wlanAttr)),
|
||||||
|
uintptr(unsafe.Pointer(nil)))
|
||||||
|
if e != 0 {
|
||||||
|
env.log(Error, "parseNetworkInterface", "wlan_intf_opcode_current_connection error")
|
||||||
|
return &info, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SSID
|
||||||
|
ssid := wlanAttr.wlanAssociationAttributes.dot11Ssid
|
||||||
|
if ssid.uSSIDLength > 0 {
|
||||||
|
info.SSID = string(ssid.ucSSID[0:ssid.uSSIDLength])
|
||||||
|
}
|
||||||
|
|
||||||
|
// see https://docs.microsoft.com/en-us/windows/win32/nativewifi/dot11-phy-type
|
||||||
|
switch wlanAttr.wlanAssociationAttributes.dot11PhyType {
|
||||||
|
case 1:
|
||||||
|
info.PhysType = FHSS
|
||||||
|
case 2:
|
||||||
|
info.PhysType = DSSS
|
||||||
|
case 3:
|
||||||
|
info.PhysType = IR
|
||||||
|
case 4:
|
||||||
|
info.PhysType = A
|
||||||
|
case 5:
|
||||||
|
info.PhysType = HRDSSS
|
||||||
|
case 6:
|
||||||
|
info.PhysType = G
|
||||||
|
case 7:
|
||||||
|
info.PhysType = N
|
||||||
|
case 8:
|
||||||
|
info.PhysType = AC
|
||||||
|
default:
|
||||||
|
info.PhysType = Unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
// see https://docs.microsoft.com/en-us/windows/win32/nativewifi/dot11-bss-type
|
||||||
|
switch wlanAttr.wlanAssociationAttributes.dot11BssType {
|
||||||
|
case 1:
|
||||||
|
info.RadioType = Infrastructure
|
||||||
|
case 2:
|
||||||
|
info.RadioType = Independent
|
||||||
|
default:
|
||||||
|
info.RadioType = Any
|
||||||
|
}
|
||||||
|
|
||||||
|
info.Signal = int(wlanAttr.wlanAssociationAttributes.wlanSignalQuality)
|
||||||
|
info.TransmitRate = int(wlanAttr.wlanAssociationAttributes.ulTxRate) / 1024
|
||||||
|
info.ReceiveRate = int(wlanAttr.wlanAssociationAttributes.ulRxRate) / 1024
|
||||||
|
|
||||||
|
// Query wifi channel
|
||||||
|
dataSize = 0
|
||||||
|
var channel *uint32
|
||||||
|
e, _, err = hWlanQueryInterface.Call(uintptr(clientHandle),
|
||||||
|
uintptr(unsafe.Pointer(&network.InterfaceGuid)),
|
||||||
|
uintptr(8), // wlan_intf_opcode_channel_number
|
||||||
|
uintptr(unsafe.Pointer(nil)),
|
||||||
|
uintptr(unsafe.Pointer(&dataSize)),
|
||||||
|
uintptr(unsafe.Pointer(&channel)),
|
||||||
|
uintptr(unsafe.Pointer(nil)))
|
||||||
|
if e != 0 {
|
||||||
|
env.log(Error, "parseNetworkInterface", "wlan_intf_opcode_channel_number error")
|
||||||
|
return &info, err
|
||||||
|
}
|
||||||
|
info.Channel = int(*channel)
|
||||||
|
|
||||||
|
if wlanAttr.wlanSecurityAttributes.bSecurityEnabled <= 0 {
|
||||||
|
info.Authentication = Disabled
|
||||||
|
return &info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// see https://docs.microsoft.com/en-us/windows/win32/nativewifi/dot11-auth-algorithm
|
||||||
|
switch wlanAttr.wlanSecurityAttributes.dot11AuthAlgorithm {
|
||||||
|
case 1:
|
||||||
|
info.Authentication = OpenSystem
|
||||||
|
case 2:
|
||||||
|
info.Authentication = SharedKey
|
||||||
|
case 3:
|
||||||
|
info.Authentication = WPA
|
||||||
|
case 4:
|
||||||
|
info.Authentication = WPAPSK
|
||||||
|
case 5:
|
||||||
|
info.Authentication = WPANone
|
||||||
|
case 6:
|
||||||
|
info.Authentication = WPA2
|
||||||
|
case 7:
|
||||||
|
info.Authentication = WPA2PSK
|
||||||
|
default:
|
||||||
|
info.Authentication = Unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
// see https://docs.microsoft.com/en-us/windows/win32/nativewifi/dot11-cipher-algorithm
|
||||||
|
switch wlanAttr.wlanSecurityAttributes.dot11CipherAlgorithm {
|
||||||
|
case 0:
|
||||||
|
info.Cipher = None
|
||||||
|
case 0x1:
|
||||||
|
info.Cipher = WEP40
|
||||||
|
case 0x2:
|
||||||
|
info.Cipher = TKIP
|
||||||
|
case 0x4:
|
||||||
|
info.Cipher = CCMP
|
||||||
|
case 0x5:
|
||||||
|
info.Cipher = WEP104
|
||||||
|
case 0x100:
|
||||||
|
info.Cipher = WPA
|
||||||
|
case 0x101:
|
||||||
|
info.Cipher = WEP
|
||||||
|
default:
|
||||||
|
info.Cipher = Unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type WLAN_INTERFACE_INFO_LIST struct { // nolint: revive
|
||||||
|
dwNumberOfItems uint32
|
||||||
|
dwIndex uint32 // nolint: structcheck,unused
|
||||||
|
InterfaceInfo [1]WLAN_INTERFACE_INFO
|
||||||
|
}
|
||||||
|
|
||||||
|
type WLAN_INTERFACE_INFO struct { // nolint: revive
|
||||||
|
InterfaceGuid syscall.GUID // nolint: revive
|
||||||
|
strInterfaceDescription [256]uint16
|
||||||
|
isState uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type WLAN_CONNECTION_ATTRIBUTES struct { // nolint: revive
|
||||||
|
isState uint32 // nolint: structcheck,unused
|
||||||
|
wlanConnectionMode uint32 // nolint: structcheck,unused
|
||||||
|
strProfileName [256]uint16 // nolint: structcheck,unused
|
||||||
|
wlanAssociationAttributes WLAN_ASSOCIATION_ATTRIBUTES
|
||||||
|
wlanSecurityAttributes WLAN_SECURITY_ATTRIBUTES
|
||||||
|
}
|
||||||
|
|
||||||
|
type WLAN_ASSOCIATION_ATTRIBUTES struct { // nolint: revive
|
||||||
|
dot11Ssid DOT11_SSID
|
||||||
|
dot11BssType uint32
|
||||||
|
dot11Bssid [6]uint8 // nolint: structcheck,unused
|
||||||
|
dot11PhyType uint32
|
||||||
|
uDot11PhyIndex uint32 // nolint: structcheck,unused
|
||||||
|
wlanSignalQuality uint32
|
||||||
|
ulRxRate uint32
|
||||||
|
ulTxRate uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type WLAN_SECURITY_ATTRIBUTES struct { // nolint: revive
|
||||||
|
bSecurityEnabled uint32
|
||||||
|
bOneXEnabled uint32 // nolint: structcheck,unused
|
||||||
|
dot11AuthAlgorithm uint32
|
||||||
|
dot11CipherAlgorithm uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type DOT11_SSID struct { // nolint: revive
|
||||||
|
uSSIDLength uint32
|
||||||
|
ucSSID [32]uint8
|
||||||
|
}
|
||||||
|
|
|
@ -198,6 +198,11 @@ func (env *MockedEnvironment) convertToLinuxPath(path string) string {
|
||||||
return args.String(0)
|
return args.String(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (env *MockedEnvironment) getWifiNetwork() (*wifiInfo, error) {
|
||||||
|
args := env.Called(nil)
|
||||||
|
return args.Get(0).(*wifiInfo), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
homeBill = "/home/bill"
|
homeBill = "/home/bill"
|
||||||
homeJan = "/usr/home/jan"
|
homeJan = "/usr/home/jan"
|
||||||
|
|
|
@ -1,27 +1,14 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type wifi struct {
|
type wifi struct {
|
||||||
props properties
|
props properties
|
||||||
env environmentInfo
|
env environmentInfo
|
||||||
Connected bool
|
|
||||||
State string
|
wifiInfo
|
||||||
SSID string
|
|
||||||
RadioType string
|
|
||||||
Authentication string
|
|
||||||
Channel int
|
|
||||||
ReceiveRate int
|
|
||||||
TransmitRate int
|
|
||||||
Signal int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultTemplate = "{{ if .Connected }}\uFAA8{{ else }}\uFAA9{{ end }}{{ if .Connected }}{{ .SSID }} {{ .Signal }}% {{ .ReceiveRate }}Mbps{{ else }}{{ .State }}{{ end }}"
|
defaultTemplate = "{{ if .Error }}{{ .Error }}{{ else }}\uFAA8 {{ .SSID }} {{ .Signal }}% {{ .ReceiveRate }}Mbps{{ end }}"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (w *wifi) enabled() bool {
|
func (w *wifi) enabled() bool {
|
||||||
|
@ -29,27 +16,16 @@ func (w *wifi) enabled() bool {
|
||||||
if w.env.getPlatform() != windowsPlatform && !w.env.isWsl() {
|
if w.env.getPlatform() != windowsPlatform && !w.env.isWsl() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
wifiInfo, err := w.env.getWifiNetwork()
|
||||||
// Bail out of no netsh command found
|
|
||||||
cmd := "netsh.exe"
|
|
||||||
if !w.env.hasCommand(cmd) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to retrieve output from netsh command
|
|
||||||
cmdResult, err := w.env.runCommand(cmd, "wlan", "show", "interfaces")
|
|
||||||
displayError := w.props.getBool(DisplayError, false)
|
displayError := w.props.getBool(DisplayError, false)
|
||||||
if err != nil && displayError {
|
if err != nil && displayError {
|
||||||
w.State = fmt.Sprintf("WIFI ERR: %s", err)
|
w.Error = err.Error()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil || wifiInfo == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
w.wifiInfo = *wifiInfo
|
||||||
// Extract data from netsh cmdResult
|
|
||||||
parseNetshCmdResult(cmdResult, w)
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,43 +48,3 @@ func (w *wifi) init(props properties, env environmentInfo) {
|
||||||
w.props = props
|
w.props = props
|
||||||
w.env = env
|
w.env = env
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseNetshCmdResult(netshCmdResult string, w *wifi) {
|
|
||||||
lines := strings.Split(netshCmdResult, "\n")
|
|
||||||
for _, line := range lines {
|
|
||||||
matches := strings.Split(line, " : ")
|
|
||||||
if len(matches) != 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
name := strings.TrimSpace(matches[0])
|
|
||||||
value := strings.TrimSpace(matches[1])
|
|
||||||
|
|
||||||
switch name {
|
|
||||||
case "State":
|
|
||||||
w.State = value
|
|
||||||
w.Connected = value == "connected"
|
|
||||||
case "SSID":
|
|
||||||
w.SSID = value
|
|
||||||
case "Radio type":
|
|
||||||
w.RadioType = value
|
|
||||||
case "Authentication":
|
|
||||||
w.Authentication = value
|
|
||||||
case "Channel":
|
|
||||||
if intValue, err := strconv.Atoi(value); err == nil {
|
|
||||||
w.Channel = intValue
|
|
||||||
}
|
|
||||||
case "Receive rate (Mbps)":
|
|
||||||
if intValue, err := strconv.Atoi(strings.Split(value, ".")[0]); err == nil {
|
|
||||||
w.ReceiveRate = intValue
|
|
||||||
}
|
|
||||||
case "Transmit rate (Mbps)":
|
|
||||||
if intValue, err := strconv.Atoi(strings.Split(value, ".")[0]); err == nil {
|
|
||||||
w.TransmitRate = intValue
|
|
||||||
}
|
|
||||||
case "Signal":
|
|
||||||
if intValue, err := strconv.Atoi(strings.TrimRight(value, "%")); err == nil {
|
|
||||||
w.Signal = intValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,114 +2,41 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/mock"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type netshStringArgs struct {
|
|
||||||
state string
|
|
||||||
ssid string
|
|
||||||
radioType string
|
|
||||||
authentication string
|
|
||||||
channel int
|
|
||||||
receiveRate int
|
|
||||||
transmitRate int
|
|
||||||
signal int
|
|
||||||
}
|
|
||||||
|
|
||||||
func getNetshString(args *netshStringArgs) string {
|
|
||||||
const netshString string = `
|
|
||||||
There is 1 interface on the system:
|
|
||||||
|
|
||||||
Name : Wi-Fi
|
|
||||||
Description : Intel(R) Wireless-AC 9560 160MHz
|
|
||||||
GUID : 6bb8def2-9af2-4bd4-8be2-6bd54e46bdc9
|
|
||||||
Physical address : d4:3b:04:e6:10:40
|
|
||||||
State : %s
|
|
||||||
SSID : %s
|
|
||||||
BSSID : 5c:7d:7d:82:c5:73
|
|
||||||
Network type : Infrastructure
|
|
||||||
Radio type : %s
|
|
||||||
Authentication : %s
|
|
||||||
Cipher : CCMP
|
|
||||||
Connection mode : Profile
|
|
||||||
Channel : %d
|
|
||||||
Receive rate (Mbps) : %d
|
|
||||||
Transmit rate (Mbps) : %d
|
|
||||||
Signal : %d%%
|
|
||||||
Profile : ohsiggy
|
|
||||||
|
|
||||||
Hosted network status : Not available`
|
|
||||||
|
|
||||||
return fmt.Sprintf(netshString, args.state, args.ssid, args.radioType, args.authentication, args.channel, args.receiveRate, args.transmitRate, args.signal)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWiFiSegment(t *testing.T) {
|
func TestWiFiSegment(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
Case string
|
Case string
|
||||||
ExpectedString string
|
ExpectedString string
|
||||||
ExpectedEnabled bool
|
ExpectedEnabled bool
|
||||||
CommandNotFound bool
|
Network *wifiInfo
|
||||||
CommandOutput string
|
WifiError error
|
||||||
CommandError error
|
|
||||||
DisplayError bool
|
DisplayError bool
|
||||||
Template string
|
|
||||||
ExpectedState string
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
Case: "not enabled on windows when netsh command not found",
|
Case: "No error and nil network",
|
||||||
ExpectedEnabled: false,
|
|
||||||
ExpectedString: "",
|
|
||||||
CommandNotFound: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Case: "not enabled on windows when netsh command fails",
|
Case: "Error and nil network",
|
||||||
ExpectedEnabled: false,
|
WifiError: errors.New("oh noes"),
|
||||||
ExpectedString: "",
|
|
||||||
CommandError: errors.New("intentional testing failure"),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Case: "enabled on windows with DisplayError=true",
|
Case: "Display error and nil network",
|
||||||
ExpectedEnabled: true,
|
WifiError: errors.New("oh noes"),
|
||||||
ExpectedString: "WIFI ERR: intentional testing failure",
|
ExpectedString: "oh noes",
|
||||||
CommandError: errors.New("intentional testing failure"),
|
|
||||||
DisplayError: true,
|
DisplayError: true,
|
||||||
Template: "{{.State}}",
|
ExpectedEnabled: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Case: "enabled on windows with every property in template",
|
Case: "Display wifi state",
|
||||||
|
ExpectedString: "pretty fly for a wifi",
|
||||||
ExpectedEnabled: true,
|
ExpectedEnabled: true,
|
||||||
ExpectedString: "connected testing 802.11ac WPA2-Personal 99 500 400 80",
|
Network: &wifiInfo{
|
||||||
CommandOutput: getNetshString(&netshStringArgs{
|
SSID: "pretty fly for a wifi",
|
||||||
state: "connected",
|
},
|
||||||
ssid: "testing",
|
|
||||||
radioType: "802.11ac",
|
|
||||||
authentication: "WPA2-Personal",
|
|
||||||
channel: 99,
|
|
||||||
receiveRate: 500.0,
|
|
||||||
transmitRate: 400.0,
|
|
||||||
signal: 80,
|
|
||||||
}),
|
|
||||||
Template: "{{.State}} {{.SSID}} {{.RadioType}} {{.Authentication}} {{.Channel}} {{.ReceiveRate}} {{.TransmitRate}} {{.Signal}}",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Case: "enabled on windows but wifi not connected",
|
|
||||||
ExpectedEnabled: true,
|
|
||||||
ExpectedString: "disconnected",
|
|
||||||
CommandOutput: getNetshString(&netshStringArgs{
|
|
||||||
state: "disconnected",
|
|
||||||
}),
|
|
||||||
Template: "{{if not .Connected}}{{.State}}{{end}}",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Case: "enabled on windows but template is invalid",
|
|
||||||
ExpectedEnabled: true,
|
|
||||||
ExpectedString: "unable to create text based on template",
|
|
||||||
CommandOutput: getNetshString(&netshStringArgs{}),
|
|
||||||
Template: "{{.DoesNotExist}}",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,18 +44,19 @@ func TestWiFiSegment(t *testing.T) {
|
||||||
env := new(MockedEnvironment)
|
env := new(MockedEnvironment)
|
||||||
env.On("getPlatform", nil).Return(windowsPlatform)
|
env.On("getPlatform", nil).Return(windowsPlatform)
|
||||||
env.On("isWsl", nil).Return(false)
|
env.On("isWsl", nil).Return(false)
|
||||||
env.On("hasCommand", "netsh.exe").Return(!tc.CommandNotFound)
|
env.On("getWifiNetwork", nil).Return(tc.Network, tc.WifiError)
|
||||||
env.On("runCommand", mock.Anything, mock.Anything).Return(tc.CommandOutput, tc.CommandError)
|
|
||||||
|
|
||||||
w := &wifi{
|
w := &wifi{
|
||||||
env: env,
|
env: env,
|
||||||
props: map[Property]interface{}{
|
props: map[Property]interface{}{
|
||||||
DisplayError: tc.DisplayError,
|
DisplayError: tc.DisplayError,
|
||||||
SegmentTemplate: tc.Template,
|
SegmentTemplate: "{{ if .Error }}{{ .Error }}{{ else }}{{ .SSID }}{{ end }}",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, tc.ExpectedEnabled, w.enabled(), tc.Case)
|
assert.Equal(t, tc.ExpectedEnabled, w.enabled(), tc.Case)
|
||||||
assert.Equal(t, tc.ExpectedString, w.string(), tc.Case)
|
if tc.Network != nil || tc.DisplayError {
|
||||||
|
assert.Equal(t, tc.ExpectedString, w.string(), tc.Case)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue