Skip to content

Commit d2a578b

Browse files
committed
Began implementing testing
1 parent a69594b commit d2a578b

5 files changed

Lines changed: 256 additions & 238 deletions

File tree

README.md

Lines changed: 29 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -30,51 +30,40 @@ CREATE TABLE users (
3030
);
3131
```
3232
A rudimentary implementation can be generated with:
33-
```rust,no_run
34-
use sql_docs::generate_docs_from_dir_no_deny;
35-
use std::path::Path;
33+
```rust
34+
use sql_docs::SqlDoc;
35+
use sql_docs::error::DocError;
36+
use std::{env, fs, path::Path};
3637

37-
fn main() -> Result<(), sql_docs::DocError> {
38-
// Directory containing your .sql files
39-
let directory = "sql_dir";
40-
41-
// Extract table + column documentation
42-
let docs = generate_docs_from_dir_no_deny(directory)?;
43-
44-
// Format and print each table and table's columns
45-
for (path, sql_docs) in docs {
46-
println!("File: {}", path.display());
47-
for table in sql_docs.tables() {
48-
println!(" Table: {}", table.name());
49-
if let Some(doc) = table.doc() {
50-
println!(" Comment: {}", doc);
51-
}
52-
println!(" Columns:");
53-
for column in table.columns() {
54-
println!(" - {}", column.name());
55-
if let Some(col_doc) = column.doc() {
56-
println!(" {}", col_doc);
57-
}
58-
}
59-
}
60-
}
38+
fn main() -> Result<(), DocError> {
39+
// tmp dir and file created for demonstration purposes
40+
let base = env::temp_dir().join("tmp_dir");
41+
let _ = fs::remove_dir_all(&base);
42+
fs::create_dir_all(&base)?;
43+
let example = base.join("example.sql");
44+
fs::write(&example, r#"/* Table storing user accounts */
45+
CREATE TABLE users (
46+
/* Primary key for each user */
47+
id INTEGER PRIMARY KEY,
48+
-- The user's login name
49+
username VARCHAR(255) NOT NULL,
50+
/* User's email address */
51+
email VARCHAR(255) UNIQUE NOT NULL
52+
);"#)?;
6153

54+
// Extract table & column documentation
55+
let docs = SqlDoc::from_path(&example).build()?;
56+
// Verify that the table name is correct
57+
assert_eq!(docs.tables().first().expect("hardcoded value").name(), "users");
58+
// Verify extraction of table comment
59+
assert_eq!(docs.tables().first().expect("hardcoded value").doc(), Some("Table storing user accounts"));
60+
// Verify First Column name and comment
61+
assert_eq!(docs.tables().first().expect("hardcoded value").columns().first().expect("hardcoded value").name(), "id");
62+
assert_eq!(docs.tables().first().expect("hardcoded value").columns().first().expect("hardcoded value").doc(), Some("Primary key for each user"));
63+
let _ = fs::remove_dir_all(&base);
6264
Ok(())
6365
}
6466
```
65-
Which should output:
66-
```bash
67-
File: sql_dir/users.sql
68-
Table: users
69-
Comment: Table storing user accounts
70-
Columns:
71-
- id
72-
Primary key for each user
73-
- username
74-
The user's login name
75-
- email
76-
User's email address
77-
```
7867
## Use cases
7968

8069
This crate is designed for generating documentation from SQL schemas by attaching comments to:

src/error.rs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,104 @@ impl From<ParserError> for DocError {
8686
Self::SqlParserError(e)
8787
}
8888
}
89+
90+
#[cfg(test)]
91+
mod tests {
92+
use sqlparser::parser::ParserError;
93+
94+
use crate::{
95+
error::DocError, comments::CommentError
96+
};
97+
98+
#[test]
99+
fn test_doc_errors() {
100+
use std::fs;
101+
102+
use crate::comments::Location;
103+
let Err(io_error) = fs::read_dir("INVALID") else {
104+
panic!("there should not be a directory called INVALID")
105+
};
106+
let io_error_str = io_error.to_string();
107+
let read_error = DocError::FileReadError(io_error);
108+
let expected_read_error = "file read error: ".to_owned() + &io_error_str;
109+
assert!(read_error.to_string().contains(&expected_read_error));
110+
111+
let comment_error = DocError::CommentError(CommentError::UnmatchedMultilineCommentStart {
112+
location: Location::default(),
113+
});
114+
let expected_comment_error =
115+
"comment parse error: unmatched block comment start at line 1, column 1";
116+
assert_eq!(comment_error.to_string(), expected_comment_error);
117+
118+
let sql_error = DocError::SqlParserError(ParserError::RecursionLimitExceeded);
119+
let expected_sql_error = "SQL parse error sql parser error: recursion limit exceeded";
120+
assert_eq!(sql_error.to_string(), expected_sql_error);
121+
}
122+
123+
#[test]
124+
fn test_doc_errors_from() {
125+
use std::fs;
126+
127+
use crate::comments::Location;
128+
let Err(io_error) = fs::read_dir("INVALID") else {
129+
panic!("there should not be a directory called INVALID")
130+
};
131+
let io_kind = io_error.kind();
132+
let doc_io_error = DocError::from(io_error);
133+
match doc_io_error {
134+
DocError::FileReadError(inner) => assert_eq!(inner.kind(), io_kind),
135+
_ => panic!("expected instance of DocError::FileReadError"),
136+
}
137+
138+
let comment_error =
139+
CommentError::UnmatchedMultilineCommentStart { location: Location::default() };
140+
let comment_error_str = comment_error.to_string();
141+
let doc_comment_error: DocError = comment_error.into();
142+
match doc_comment_error {
143+
DocError::CommentError(inner) => assert_eq!(inner.to_string(), comment_error_str),
144+
_ => panic!("expected instance of DocError::CommentError"),
145+
}
146+
147+
let parser_error = ParserError::RecursionLimitExceeded;
148+
let parser_error_str = parser_error.to_string();
149+
let doc_parser_error: DocError = parser_error.into();
150+
match doc_parser_error {
151+
DocError::SqlParserError(inner) => assert_eq!(inner.to_string(), parser_error_str),
152+
_ => panic!("expected instance of DocError::SqlParserError"),
153+
}
154+
}
155+
156+
#[test]
157+
fn test_doc_error_source() {
158+
use std::{error::Error, fs};
159+
160+
use crate::comments::Location;
161+
162+
let Err(io_err) = fs::read_dir("INVALID") else {
163+
panic!("there should not be a directory called INVALID")
164+
};
165+
let io_err_str = io_err.to_string();
166+
let doc_io = DocError::FileReadError(io_err);
167+
let src = doc_io
168+
.source()
169+
.map_or_else(|| panic!("expected Some(source) for FileReadError"), |source| source);
170+
assert_eq!(src.to_string(), io_err_str);
171+
172+
let comment =
173+
CommentError::UnmatchedMultilineCommentStart { location: Location::default() };
174+
let comment_str = comment.to_string();
175+
let doc_comment = DocError::CommentError(comment);
176+
let src = doc_comment
177+
.source()
178+
.map_or_else(|| panic!("expected Some(source) for CommentError"), |source| source);
179+
assert_eq!(src.to_string(), comment_str);
180+
181+
let parser = ParserError::RecursionLimitExceeded;
182+
let parser_str = parser.to_string();
183+
let doc_parser = DocError::SqlParserError(parser);
184+
let src = doc_parser
185+
.source()
186+
.map_or_else(|| panic!("expected Some(source) for SqlParserError"), |source| source);
187+
assert_eq!(src.to_string(), parser_str);
188+
}
189+
}

src/files.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ mod tests {
188188
#[test]
189189
fn test_recursive_scan_finds_only_sql_files_recursively()
190190
-> Result<(), Box<dyn std::error::Error>> {
191-
let base = env::temp_dir().join("recursive_scan_test");
191+
let base = env::temp_dir().join("recursive_scan_test_sql");
192192
let _ = fs::remove_dir_all(&base);
193193
fs::create_dir_all(&base)?;
194194
let sub = base.join("subdir");
@@ -210,6 +210,30 @@ mod tests {
210210
Ok(())
211211
}
212212

213+
#[test]
214+
fn test_recursive_dir_scan_errs() -> Result<(), Box<dyn std::error::Error>>{
215+
let base = env::temp_dir().join("recursive_scan_test");
216+
let _ = fs::remove_dir_all(&base);
217+
fs::create_dir_all(&base)?;
218+
let sub = base.join("subdir");
219+
fs::create_dir_all(&sub)?;
220+
let file1 = base.join("one.sql");
221+
let file2 = sub.join("two.sql");
222+
let non_sql1 = base.join("ignore.txt");
223+
let non_sql2 = sub.join("README.md");
224+
fs::File::create(&file1)?;
225+
fs::File::create(&file2)?;
226+
fs::File::create(&non_sql1)?;
227+
fs::File::create(&non_sql2)?;
228+
229+
let bad_path = Path::new("bad_path");
230+
let bad_dir_scan = recursive_dir_scan(bad_path);
231+
assert!(bad_dir_scan.is_err());
232+
233+
let _ = fs::remove_dir_all(&base);
234+
Ok(())
235+
}
236+
213237
#[test]
214238
fn test_sql_file_list() -> Result<(), Box<dyn std::error::Error>> {
215239
let base = env::temp_dir().join("recursive_scan_test2");

0 commit comments

Comments
 (0)