Skip to content

Commit

Permalink
Unit tests (#2)
Browse files Browse the repository at this point in the history
* Add information about default configuration in Readme

* Completely re-write logic behing parseConfig

* Add unit test for parseConfig for directory perms 000, 100, 200, 300

* Add unit test for parseConfig for directory perms 400,500,600,700

* Move error message generation from main to CloseApp and OpenApp directly

* Remove unnescessary white-spaces

* Move determineAction into a separate method so it can be unit tested
  • Loading branch information
SimonTheLeg authored Aug 12, 2018
1 parent f355453 commit 94f8ff6
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 34 deletions.
2 changes: 1 addition & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Currently only working with Mac OS X, more variety to come soon.

## Set-Up

create a config file under ~/.deepwork/config.json and add the names of all communication applications. An example config can be found in [example-config.json](example-config.json)
create a config file under ~/.deepwork/config.json and add the names of all communication applications. An example config can be found in [example-config.json](example-config.json). By default Mail and Calendar will be added.

## Usage

Expand Down
6 changes: 2 additions & 4 deletions applescriptHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import (
"strings"
)



// OpenApp opens an application using AppleScript
func OpenApp(appName string) error {
script := fmt.Sprintf(`
Expand All @@ -18,7 +16,7 @@ end tell

err := ExecuteAppleScript(script)

return err
return fmt.Errorf("Could not open app '%s': '%v'", appName, err)
}

// CloseApp closes an application using AppleScript
Expand All @@ -31,7 +29,7 @@ end tell

err := ExecuteAppleScript(script)

return err
return fmt.Errorf("Could not close app '%s': '%v'", appName, err)
}

// ExecuteAppleScript takes in a fully parsed Apple-Script executes the command using osascript
Expand Down
67 changes: 38 additions & 29 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"io/ioutil"
"log"
"os"
"strings"
"path"

homedir "github.com/mitchellh/go-homedir"
)
Expand Down Expand Up @@ -35,53 +35,62 @@ func main() {

// Parse Command Line Flags
flag.Parse()
desStage := flag.Arg(0)
desAction := flag.Arg(0)

// Determine desired action
var action func(name string) error
switch desStage {
case "on":
action = CloseApp
case "off":
action = OpenApp
default:
fmt.Println("Usage: deepwork [on,off]")
os.Exit(1)
}
action = determineAction(desAction)

// Execute action
for _, app := range config.AffectedApps {
err := action(app)
if err != nil {
log.Printf("Could not close app %s: %v", app, err)
log.Printf("%v", err)
}
}
}

func determineAction(desAction string) func(name string) error {
switch desAction {
case "on":
return CloseApp
case "off":
return OpenApp
default:
return nil
}
}

func parseConfig(configLocation string) (config, error) {
var conf config
confDir := path.Dir(configLocation)

// Try to open config
jsonFile, err := os.Open(configLocation)
defer jsonFile.Close()
if err != nil {
// Check if there is already a config file => harmless case, just create default conf
if os.IsNotExist(err) {
defaultConfig := []byte(`{"affectedApps":["Mail","Calendar"]}`)

// Create required directories if necessary
if err = os.Mkdir(strings.TrimRight(configLocation, "/config.json"), 0744); err != nil {
return config{}, fmt.Errorf("Could not create required directories for config: %v", err)
}
// Write File
if err = ioutil.WriteFile(configLocation, defaultConfig, 0644); err != nil {
return config{}, fmt.Errorf("Could not write default config: %v", err)
}
// Call itself again to parse newly created conf
return parseConfig(configLocation)

// Check if there is a config file at the specified location, if not create a default config
if os.IsNotExist(err) {
defaultConfig := []byte(`{"affectedApps":["Mail","Calendar"]}`)

// Create required directories if necessary
if err = os.MkdirAll(confDir, 0744); err != nil {
return config{}, fmt.Errorf("Could not create required directories for config: %v", err)
}
// Otherwise (e.g. no permissions on conf file), return the error
return config{}, err
// Write default config
if err = ioutil.WriteFile(configLocation, defaultConfig, 0644); err != nil {
return config{}, fmt.Errorf("Could not write default config: %v", err)
}
// Call itself again to parse newly created conf
return parseConfig(configLocation)
}

// Otherwise (e.g. no permissions on conf file or it's dir), return the error
if err != nil {
return config{}, fmt.Errorf("Could not access config file: %v", err)
}

// Read in the config
confByte, err := ioutil.ReadAll(jsonFile)

if err != nil {
Expand Down
118 changes: 118 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package main

import (
"bytes"
"io/ioutil"
"log"
"os"
"path"
"testing"

homedir "github.com/mitchellh/go-homedir"
)

var UserHomeDir string

func init() {
// Determine Users home directory
var err error
UserHomeDir, err = homedir.Dir()
if err != nil {
log.Fatalf("Could not determine Users home directory: %v", err)
}
}

func TestParseConfig(t *testing.T) {
difFolderPerm := []struct {
name string
folderPerm os.FileMode
configLocation string
expResp string
}{
{
"no perm, directory exists",
0000,
"/tmp/noPermissionsHere/config.json",
"Could not access config file: open /tmp/noPermissionsHere/config.json: permission denied",
},
{
"execute only, directory doesn't exist yet",
0100,
"/tmp/executeOnly/config.json",
"Could not write default config: open /tmp/executeOnly/config.json: permission denied",
},
{
"write only",
0200,
"/tmp/writeOnly/config.json",
"Could not access config file: open /tmp/writeOnly/config.json: permission denied",
},
{
"write & execute",
0300,
"/tmp/writeAndExecute/config.json",
"no error",
}, {
"read only",
0400,
"/tmp/readOnly/config.json",
"Could not access config file: open /tmp/readOnly/config.json: permission denied",
}, {
"read & execute",
0500,
"/tmp/readAndExecute/config.json",
"Could not write default config: open /tmp/readAndExecute/config.json: permission denied",
}, {
"read & write",
0600,
"/tmp/readAndWrite/config.json",
"Could not access config file: open /tmp/readAndWrite/config.json: permission denied",
}, {
"all permissions",
0700,
"/tmp/allPermissions/config.json",
"no error",
},
}

for _, tc := range difFolderPerm {
t.Run(tc.name, func(t *testing.T) {
confDir := path.Dir(tc.configLocation)

if err := os.Mkdir(confDir, tc.folderPerm); err != nil {
t.Fatalf("Could not create dir: %s: %v", confDir, err)
}

_, err := parseConfig(tc.configLocation)

// Check if the response from parseConfig, is the expected one
if err != nil {
if err.Error() != tc.expResp {
t.Errorf("Expected: '%v' got: '%v'", tc.expResp, err.Error())
}
} else {
if tc.expResp != "no error" {
t.Errorf("Got no error, but expected '%v'", tc.expResp)
}
}

// Make sure in the successful cases the file is actually there
if tc.expResp == "no error" {
cont, err := ioutil.ReadFile(tc.configLocation)
if err != nil {
t.Errorf("Expected a file at %s, but could not read it due to: %v", tc.configLocation, err)
}
defaultConfig := []byte(`{"affectedApps":["Mail","Calendar"]}`)
if bytes.Compare(cont, defaultConfig) != 0 {
t.Errorf("%s should have the following content: '%v', but has '%v'", tc.configLocation, defaultConfig, cont)
}
}

// Clean up
os.Chmod(confDir, 0700)
if err := os.RemoveAll(confDir); err != nil {
t.Fatalf("Could not clean up '%s': %v; Please clean up this directory manually, as it can corrupt further testing", confDir, err)
}
})
}
}

0 comments on commit 94f8ff6

Please sign in to comment.