Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 43 additions & 4 deletions src/clojure_mcp/utils/valid_paths.clj
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,51 @@
(defn path-exists? [path]
(.exists (io/file path)))

(defn- clojure-source-ext?
"Returns true if the file path has a Clojure source extension (.clj, .cljs, .cljc, .cljd)
that follows the dash-to-underscore filename convention."
[file-path]
(when file-path
(let [lower-path (str/lower-case file-path)]
(or (str/ends-with? lower-path ".clj")
(str/ends-with? lower-path ".cljs")
(str/ends-with? lower-path ".cljc")
(str/ends-with? lower-path ".cljd")))))

(defn- try-dash-to-underscore-correction
"When a validated path doesn't exist and has a Clojure source extension,
tries replacing dashes with underscores in the filename part only
(not directory components). Returns the re-validated corrected path
if the file exists, nil otherwise."
[validated-path current-dir allowed-dirs]
(when (clojure-source-ext? validated-path)
(let [file (io/file validated-path)
parent (.getParentFile file)
filename (.getName file)
corrected-filename (str/replace filename "-" "_")]
(when (not= filename corrected-filename)
(let [corrected-file (if parent
(io/file parent corrected-filename)
(io/file corrected-filename))
corrected-path (.getPath corrected-file)]
(when (path-exists? corrected-path)
;; Re-validate for defense-in-depth (symlink protection)
(validate-path corrected-path current-dir allowed-dirs)))))))

(defn validate-path-with-client
"Validates a path using settings from the nrepl-client.

Parameters:
- path: The path to validate (can be relative or absolute)
- nrepl-client-map: The nREPL client map (dereferenced atom)

Returns:
- The normalized absolute path if valid
- Throws an exception if the path is invalid or if required settings are missing"
- Throws an exception if the path is invalid or if required settings are missing

When the validated path doesn't exist and has a Clojure source extension
(.clj, .cljs, .cljc, .cljd), tries replacing dashes with underscores in the
filename (not directory components) and returns the corrected path if it exists."
[path nrepl-client]
(let [current-dir (config/get-nrepl-user-dir nrepl-client)
allowed-dirs (config/get-allowed-directories nrepl-client)]
Expand All @@ -80,7 +115,11 @@
(throw (ex-info "Missing allowed-directories in config"
{:client-keys (keys nrepl-client)})))

(validate-path path current-dir allowed-dirs)))
(let [validated (validate-path path current-dir allowed-dirs)]
(if (path-exists? validated)
validated
(or (try-dash-to-underscore-correction validated current-dir allowed-dirs)
validated)))))
Comment on lines +118 to +122
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether unified-read-file surfaces correction metadata/notice in its response contract.

# 1) Find path-validation callsites and nearby response construction.
rg -n -C4 'validate-path-with-client|validate-inputs|execute-tool|format-results' src/clojure_mcp/tools/unified_read_file test/clojure_mcp/tools/unified_read_file

# 2) Search for correction-related fields/strings in tool code and tests.
rg -n -C3 'corrected|correction|original-path|original_filename|notice|dash|underscore' src test

Repository: bhauman/clojure-mcp

Length of output: 47980


🏁 Script executed:

# Check what execute-tool returns for unified-read-file
rg -n -A 20 'defmethod tool-system/execute-tool :unified-read-file' src/clojure_mcp/tools/unified_read_file/tool.clj | head -50

# Check the result structure being returned
rg -n -B 5 -A 10 'defn execute-tool\|execute-tool.*result' src/clojure_mcp/tools/unified_read_file/tool.clj | head -80

# Look at what's in the result map returned
rg -n ':result\|:path\|:error' src/clojure_mcp/tools/unified_read_file/tool.clj | head -40

Repository: bhauman/clojure-mcp

Length of output: 1295


🏁 Script executed:

# Get the complete execute-tool method implementation
rg -n -A 100 'defmethod tool-system/execute-tool :unified-read-file' src/clojure_mcp/tools/unified_read_file/tool.clj | head -150

# Now check format-results to see what it includes
rg -n -A 30 'defmethod tool-system/format-results :unified-read-file' src/clojure_mcp/tools/unified_read_file/tool.clj

Repository: bhauman/clojure-mcp

Length of output: 6567


🏁 Script executed:

# Check what format-raw-file returns to see if path is included
rg -n -B 5 -A 20 'defn format-raw-file' src/clojure_mcp/tools/unified_read_file/tool.clj

# Search for issue `#48` reference
rg -n '#48\|issue 48' src test

# Check if there's any correction metadata/flag being tracked anywhere
rg -n 'correction-notice\|corrected-path\|original-path\|was-corrected' src test

Repository: bhauman/clojure-mcp

Length of output: 1400


🏁 Script executed:

# Search more broadly for correction references
rg -n 'correction\|corrected\|notice' src/clojure_mcp/tools/unified_read_file test/clojure_mcp/tools/unified_read_file

# Look at the actual response structure in tests - do they check for path metadata?
rg -n -B 5 -A 5 ':path\|:corrected\|:notice' test/clojure_mcp/tools/unified_read_file/tool_test.clj

# Check what the MCP tool response contract looks like
rg -n 'result\|response' src/clojure_mcp/tool_system.clj | head -40

Repository: bhauman/clojure-mcp

Length of output: 45


🏁 Script executed:

# Check the final response structure more explicitly - what does the callback return?
cat -n src/clojure_mcp/tool_system.clj | grep -A 20 'tool-fn.*params.*callback'

# Look for any existing correction metadata handling
fd 'issue\|Issue' src test --type f -x cat {} \; | head -100

# Check unified-read-file responses in actual test assertions
rg -n 'result\|:error' test/clojure_mcp/tools/unified_read_file/tool_test.clj | grep -A 2 -B 2 'is ('

Repository: bhauman/clojure-mcp

Length of output: 1438


Correction metadata should be surfaced in read_file responses.

The path validation transparently corrects dash-to-underscore mismatches but returns only the corrected path string without metadata. The downstream response from format-results includes the corrected path only as embedded text in markdown, not as an explicit flag or notice in the response structure. Per issue #48, read_file should include both the corrected filename and an explicit correction indicator (e.g., {"corrected_path": "...", "original_path": "...", "notice": "..."}) in its structured response, not just in the formatted markdown text.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/clojure_mcp/utils/valid_paths.clj` around lines 118 - 122, The
validate-path flow currently returns only the (possibly corrected) path string;
update it and callers so dash-to-underscore corrections are surfaced as
structured metadata: have validate-path (or a new helper used here) return a map
like {:path validated-path :original original-path :corrected? true/false
:correction-source :dash-to-underscore} when try-dash-to-underscore-correction
is applied (use the existing try-dash-to-underscore-correction, path-exists? and
validate-path symbols to detect correction), and modify read_file/format-results
callers to consume this map and include explicit fields (e.g. corrected_path,
original_path, notice) in the read_file response object instead of relying only
on markdown text.


(defn- babashka-shebang?
[file-path]
Expand Down
93 changes: 90 additions & 3 deletions test/clojure_mcp/tools/unified_read_file/tool_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
[clojure-mcp.tools.unified-read-file.tool :as unified-read-file-tool]
[clojure-mcp.tool-system :as tool-system]
[clojure-mcp.config :as config]
[clojure.java.io :as io]))
[clojure.java.io :as io]
[clojure.string :as str]))

;; Setup test fixtures
(test-utils/apply-fixtures *ns*)
Expand All @@ -27,9 +28,10 @@
(try
(f)
(finally
;; Clean up
;; Clean up all files recursively
(when (.exists test-dir)
(.delete test-dir)))))))
(doseq [file (reverse (file-seq test-dir))]
(.delete file))))))))

(use-fixtures :each setup-test-files-fixture)

Expand Down Expand Up @@ -93,3 +95,88 @@
formatted-str (first formatted)]
(is (not (re-find #"truncated" formatted-str))
"Should not show truncation message when not truncated"))))

;; --- Dash-to-underscore filename correction integration tests ---
;; The core correction logic is tested in valid_paths_test.clj.
;; These tests verify the read_file tool pipeline works with the correction.

(deftest dash-to-underscore-correction-test
(testing "File with dashes requested, underscore version exists - reads successfully"
(let [underscore-file (io/file *test-dir* "core_stuff.clj")
_ (spit underscore-file "(ns core-stuff)\n(defn hello [] :world)")
tool-instance (unified-read-file-tool/create-unified-read-file-tool *nrepl-client-atom*)
dash-path (.getAbsolutePath (io/file *test-dir* "core-stuff.clj"))
validated (tool-system/validate-inputs tool-instance {:path dash-path})
result (tool-system/execute-tool tool-instance validated)
formatted (tool-system/format-results tool-instance result)]
(is (not (:error formatted)) "Should successfully read the corrected file")
(is (some #(str/includes? % "core-stuff") (:result formatted))
"Should contain the file content")
(.delete underscore-file)))

(testing "File with underscores requested directly - reads successfully"
(let [underscore-file (io/file *test-dir* "core_stuff.clj")
_ (spit underscore-file "(ns core-stuff)\n(defn hello [] :world)")
tool-instance (unified-read-file-tool/create-unified-read-file-tool *nrepl-client-atom*)
underscore-path (.getAbsolutePath underscore-file)
validated (tool-system/validate-inputs tool-instance {:path underscore-path})
result (tool-system/execute-tool tool-instance validated)
formatted (tool-system/format-results tool-instance result)]
(is (not (:error formatted)) "Should successfully read the file")
(.delete underscore-file)))

(testing "Neither dash nor underscore version exists - returns normal error"
(let [tool-instance (unified-read-file-tool/create-unified-read-file-tool *nrepl-client-atom*)
non-existent-path (.getAbsolutePath (io/file *test-dir* "no-such-file.clj"))]
(is (thrown-with-msg? clojure.lang.ExceptionInfo
#"does not exist"
(tool-system/validate-inputs tool-instance {:path non-existent-path}))
"Should throw an error when neither file version exists")))

(testing "Non-Clojure files (.java) - do NOT auto-correct"
(let [underscore-file (io/file *test-dir* "core_stuff.java")
_ (spit underscore-file "public class core_stuff {}")
tool-instance (unified-read-file-tool/create-unified-read-file-tool *nrepl-client-atom*)
dash-path (.getAbsolutePath (io/file *test-dir* "core-stuff.java"))]
(is (thrown-with-msg? clojure.lang.ExceptionInfo
#"does not exist"
(tool-system/validate-inputs tool-instance {:path dash-path}))
"Should NOT auto-correct non-Clojure file extensions")
(.delete underscore-file)))

(testing "Directory components with dashes - only filename corrected"
(let [dashed-dir (io/file *test-dir* "my-cool-dir")
_ (.mkdirs dashed-dir)
underscore-file (io/file dashed-dir "my_file.clj")
_ (spit underscore-file "(ns my-cool-dir.my-file)")
tool-instance (unified-read-file-tool/create-unified-read-file-tool *nrepl-client-atom*)
dash-path (.getAbsolutePath (io/file dashed-dir "my-file.clj"))
validated (tool-system/validate-inputs tool-instance {:path dash-path})
result (tool-system/execute-tool tool-instance validated)
formatted (tool-system/format-results tool-instance result)]
(is (not (:error formatted)) "Should read file with dashed directory and corrected filename")
(is (str/includes? (:path validated) "my-cool-dir")
"Directory dashes should be preserved")
(.delete underscore-file)
(.delete dashed-dir)))

(testing "Full pipeline through make-tool-tester with dash correction"
(let [underscore-file (io/file *test-dir* "pipeline_test.clj")
_ (spit underscore-file "(ns pipeline-test)\n(defn greet [name] (str \"Hello \" name))")
tool-instance (unified-read-file-tool/create-unified-read-file-tool *nrepl-client-atom*)
tool-fn (test-utils/make-tool-tester tool-instance)
dash-path (.getAbsolutePath (io/file *test-dir* "pipeline-test.clj"))
result (tool-fn {:path dash-path})]
(is (not (:error? result)) "Full pipeline should succeed with dash correction")
(.delete underscore-file)))

(testing "Babashka (.bb) files - do NOT auto-correct"
(let [underscore-file (io/file *test-dir* "my_script.bb")
_ (spit underscore-file "(println :hello)")
tool-instance (unified-read-file-tool/create-unified-read-file-tool *nrepl-client-atom*)
dash-path (.getAbsolutePath (io/file *test-dir* "my-script.bb"))]
(is (thrown-with-msg? clojure.lang.ExceptionInfo
#"does not exist"
(tool-system/validate-inputs tool-instance {:path dash-path}))
"Should NOT auto-correct .bb files")
(.delete underscore-file))))
Comment on lines +103 to +182
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify response-shape fields for unified-read-file and whether correction metadata exists.

# Inspect response map construction in the tool implementation.
rg -n -C5 'defn|format-results|execute|validate|:result|:error|:path|corrected|correction|notice|original' src/clojure_mcp/tools/unified_read_file

# Inspect existing tests for assertions on correction metadata/notice.
rg -n -C3 'dash-to-underscore|corrected|correction|notice|original|:path validated|format-results' test/clojure_mcp/tools/unified_read_file/tool_test.clj

Repository: bhauman/clojure-mcp

Length of output: 50377


🏁 Script executed:

#!/bin/bash
# Search for correction-related metadata in response building
rg -n "correct|original|dash|underscore" src/clojure_mcp/tools/unified_read_file/tool.clj | head -30

# Check if there's any mention of what should be in the response for corrections
rg -n "corrected\|correction\|auto.*correct" src/clojure_mcp/tools/unified_read_file/

# Look at the valid_paths module to see what validate-path-with-client returns
find src -name "*valid*" -o -name "*path*" | head -20

Repository: bhauman/clojure-mcp

Length of output: 149


🏁 Script executed:

#!/bin/bash
# Check the valid_paths implementation to understand path correction
find src -type f -name "*.clj" | xargs rg -l "validate-path-with-client" | head -5

Repository: bhauman/clojure-mcp

Length of output: 271


🏁 Script executed:

#!/bin/bash
# Look for the actual implementation of dash-to-underscore correction
rg -n "dash\|underscore\|kebab" src/clojure_mcp/tools/unified_read_file/ -A5 -B5

Repository: bhauman/clojure-mcp

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Inspect valid_paths module
cat src/clojure_mcp/utils/valid_paths.clj

Repository: bhauman/clojure-mcp

Length of output: 12403


🏁 Script executed:

#!/bin/bash
# Check if the tool response includes any correction metadata
rg -n "original\|corrected\|correction" src/clojure_mcp/tools/unified_read_file/tool.clj

Repository: bhauman/clojure-mcp

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Verify test expectations - what fields are being checked in format-results
sed -n '103,182p' test/clojure_mcp/tools/unified_read_file/tool_test.clj | grep -E "is |let \[|formatted|result"

Repository: bhauman/clojure-mcp

Length of output: 1634


🏁 Script executed:

#!/bin/bash
# Check what fields validate-path-with-client actually returns
sed -n '78,120p' src/clojure_mcp/utils/valid_paths.clj

Repository: bhauman/clojure-mcp

Length of output: 1922


🏁 Script executed:

#!/bin/bash
# Look at the full validate-inputs implementation to see all returned fields
sed -n '111,141p' src/clojure_mcp/tools/unified_read_file/tool.clj

Repository: bhauman/clojure-mcp

Length of output: 1408


🏁 Script executed:

#!/bin/bash
# Check execute-tool return structure - does it include correction metadata?
sed -n '143,217p' src/clojure_mcp/tools/unified_read_file/tool.clj | grep -E ":path|:error|:original|:corrected|:mode" | head -20

Repository: bhauman/clojure-mcp

Length of output: 602


🏁 Script executed:

#!/bin/bash
# Check format-results to see what fields are in final response
sed -n '275,299p' src/clojure_mcp/tools/unified_read_file/tool.clj

Repository: bhauman/clojure-mcp

Length of output: 909


Add assertions verifying correction metadata is included in tool responses.

Tests confirm the dash-to-underscore correction works functionally, but they don't verify that the correction is communicated to the MCP client. The current implementation silently corrects file paths without surfacing this correction in the response.

Responses need to include correction metadata (corrected filename and indication that auto-correction occurred) so users and client tools understand what path was actually accessed. This aligns with the guideline to "Validate inputs and provide helpful error messages in MCP tool implementations."

Add assertions to verify:

  1. The corrected filename appears in the response metadata
  2. The response includes a flag or notice indicating auto-correction occurred (not just relying on implicit behavior)

Example assertions to include:

  • Verify :original-path or similar field captures the requested path
  • Verify :corrected? or :correction-notice flag communicates the auto-correction to the client
  • Ensure this metadata flows through from validate-inputsexecute-toolformat-results
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/clojure_mcp/tools/unified_read_file/tool_test.clj` around lines 103 -
182, Add assertions to these tests to ensure the dash→underscore correction is
surfaced in tool metadata: after calling tool-system/validate-inputs,
tool-system/execute-tool, and tool-system/format-results (and when using
test-utils/make-tool-tester), assert that the validated/result/formatted maps
include the original requested path (e.g. :original-path or similar), a
corrected path (e.g. :path or :corrected-path showing the actual file used), and
an explicit flag/notice (e.g. :corrected? true or :correction-notice) indicating
auto-correction occurred; update each relevant testing block (the ones that read
corrected files and the full pipeline block) to check these fields flow through
validate-inputs → execute-tool → format-results using the same symbol names used
by the tool implementation
(unified-read-file-tool/create-unified-read-file-tool,
tool-system/validate-inputs, tool-system/execute-tool,
tool-system/format-results).

123 changes: 123 additions & 0 deletions test/clojure_mcp/utils/valid_paths_test.clj
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
(ns clojure-mcp.utils.valid-paths-test
(:require [clojure.test :refer [deftest is testing]]
[clojure.java.io :as io]
[clojure.string :as str]
[clojure-mcp.utils.valid-paths :as valid-paths]))

(deftest extract-paths-from-bash-command-test
Expand Down Expand Up @@ -120,6 +121,128 @@
(is (not (valid-paths/clojure-file? (.getPath tmp))))
(.delete tmp))))

(deftest dash-to-underscore-correction-test
(let [test-dir (io/file (System/getProperty "java.io.tmpdir") "valid-paths-dash-test")
canonical-dir (.getCanonicalPath test-dir)
make-client (fn []
{:clojure-mcp.config/config
{:nrepl-user-dir canonical-dir
:allowed-directories [canonical-dir]}})]
(try
(.mkdirs test-dir)

(testing "Clojure file with dashes corrected to underscores when underscore version exists"
(let [underscore-file (io/file test-dir "core_stuff.clj")
_ (spit underscore-file "(ns core-stuff)")
dash-path (.getAbsolutePath (io/file test-dir "core-stuff.clj"))
result (valid-paths/validate-path-with-client dash-path (make-client))]
(is (= (.getCanonicalPath underscore-file) result))
(.delete underscore-file)))

(testing "Non-Clojure files (.java) do NOT get corrected"
(let [underscore-file (io/file test-dir "core_stuff.java")
_ (spit underscore-file "public class core_stuff {}")
dash-path (.getAbsolutePath (io/file test-dir "core-stuff.java"))
result (valid-paths/validate-path-with-client dash-path (make-client))]
(is (not= (.getCanonicalPath underscore-file) result))
(.delete underscore-file)))

(testing "Non-Clojure files (.py) do NOT get corrected"
(let [underscore-file (io/file test-dir "my_module.py")
_ (spit underscore-file "def hello(): pass")
dash-path (.getAbsolutePath (io/file test-dir "my-module.py"))
result (valid-paths/validate-path-with-client dash-path (make-client))]
(is (not= (.getCanonicalPath underscore-file) result))
(.delete underscore-file)))

(testing "File where dashed version exists is returned as-is"
(let [dash-file (io/file test-dir "core-stuff.clj")
_ (spit dash-file "(ns core-stuff)")
dash-path (.getAbsolutePath dash-file)
result (valid-paths/validate-path-with-client dash-path (make-client))]
(is (= (.getCanonicalPath dash-file) result))
(.delete dash-file)))

(testing "Directory components with dashes are NOT changed, only filename"
(let [dashed-dir (io/file test-dir "my-cool-dir")
_ (.mkdirs dashed-dir)
underscore-file (io/file dashed-dir "my_file.clj")
_ (spit underscore-file "(ns my-cool-dir.my-file)")
dash-path (.getAbsolutePath (io/file dashed-dir "my-file.clj"))
result (valid-paths/validate-path-with-client dash-path (make-client))]
(is (= (.getCanonicalPath underscore-file) result))
(is (str/includes? result "my-cool-dir")
"Directory dashes should be preserved")
(.delete underscore-file)
(.delete dashed-dir)))

(testing ".cljs extension works"
(let [underscore-file (io/file test-dir "my_component.cljs")
_ (spit underscore-file "(ns my-component)")
dash-path (.getAbsolutePath (io/file test-dir "my-component.cljs"))
result (valid-paths/validate-path-with-client dash-path (make-client))]
(is (= (.getCanonicalPath underscore-file) result))
(.delete underscore-file)))

(testing ".cljc extension works"
(let [underscore-file (io/file test-dir "shared_utils.cljc")
_ (spit underscore-file "(ns shared-utils)")
dash-path (.getAbsolutePath (io/file test-dir "shared-utils.cljc"))
result (valid-paths/validate-path-with-client dash-path (make-client))]
(is (= (.getCanonicalPath underscore-file) result))
(.delete underscore-file)))

(testing ".cljd extension works"
(let [underscore-file (io/file test-dir "my_widget.cljd")
_ (spit underscore-file "(ns my-widget)")
dash-path (.getAbsolutePath (io/file test-dir "my-widget.cljd"))
result (valid-paths/validate-path-with-client dash-path (make-client))]
(is (= (.getCanonicalPath underscore-file) result))
(.delete underscore-file)))

(testing ".bb files are NOT corrected"
(let [underscore-file (io/file test-dir "my_script.bb")
_ (spit underscore-file "(println :hello)")
dash-path (.getAbsolutePath (io/file test-dir "my-script.bb"))
result (valid-paths/validate-path-with-client dash-path (make-client))]
(is (not= (.getCanonicalPath underscore-file) result))
(.delete underscore-file)))

(testing "When neither dashed nor underscored file exists, returns original validated path"
(let [dash-path (.getAbsolutePath (io/file test-dir "no-such-file.clj"))
result (valid-paths/validate-path-with-client dash-path (make-client))]
(is (string? result))
(is (not (valid-paths/path-exists? result)))))

(testing "Case-insensitive extension matching"
(let [underscore-file (io/file test-dir "MY_THING.CLJ")
_ (spit underscore-file "(ns my-thing)")
dash-path (.getAbsolutePath (io/file test-dir "MY-THING.CLJ"))
result (valid-paths/validate-path-with-client dash-path (make-client))]
(is (= (.getCanonicalPath underscore-file) result))
(.delete underscore-file)))

(testing "Reverse direction: underscore requested, only dash exists - should NOT correct"
(let [dash-file (io/file test-dir "core-stuff.clj")
_ (spit dash-file "(ns core-stuff)")
underscore-path (.getAbsolutePath (io/file test-dir "core_stuff.clj"))
result (valid-paths/validate-path-with-client underscore-path (make-client))]
(is (not= (.getCanonicalPath dash-file) result))
(.delete dash-file)))

(testing "Mixed dashes and underscores in filename - corrects all dashes"
(let [underscore-file (io/file test-dir "my_cool_thing.clj")
_ (spit underscore-file "(ns my-cool-thing)")
dash-path (.getAbsolutePath (io/file test-dir "my-cool_thing.clj"))
result (valid-paths/validate-path-with-client dash-path (make-client))]
(is (= (.getCanonicalPath underscore-file) result))
(.delete underscore-file)))

(finally
(when (.exists test-dir)
(doseq [file (reverse (file-seq test-dir))]
(.delete file)))))))

(deftest validate-bash-command-paths-test
(let [test-dir (.getCanonicalPath (io/file (System/getProperty "java.io.tmpdir")))
home-dir (System/getProperty "user.home")]
Expand Down
Loading