Skip to content

Commit e91403b

Browse files
committed
Increased Code Coverage for whole crate
1 parent 8bccefb commit e91403b

File tree

1 file changed

+158
-2
lines changed

1 file changed

+158
-2
lines changed

src/docs.rs

Lines changed: 158 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ impl fmt::Display for TableDoc {
126126

127127
writeln!(f, "Table Column Docs: ")?;
128128
for col in self.columns() {
129-
writeln!(f, " {col}")?;
129+
write!(f, " {col}")?;
130130
}
131131
Ok(())
132132
}
@@ -244,7 +244,17 @@ fn schema_and_table(name: &ObjectName) -> Result<(Option<String>, String), DocEr
244244

245245
#[cfg(test)]
246246
mod tests {
247-
use crate::docs::{ColumnDoc, SqlFileDoc, TableDoc};
247+
use core::fmt;
248+
249+
use sqlparser::{
250+
ast::{Ident, ObjectName, ObjectNamePart, ObjectNamePartFunction},
251+
tokenizer::Span,
252+
};
253+
254+
use crate::{
255+
docs::{ColumnDoc, SqlFileDoc, TableDoc, schema_and_table},
256+
error::DocError,
257+
};
248258

249259
#[test]
250260
fn test_sql_docs_struct() {
@@ -425,7 +435,153 @@ mod tests {
425435
#[test]
426436
fn test_doc() {
427437
let col_doc = ColumnDoc::new("test".to_string(), Some("comment".to_string()));
438+
assert_eq!(&col_doc.to_string(), &"Column Name: test\nColumn Doc: comment\n".to_string());
439+
let col_doc_no_doc = ColumnDoc::new("test".to_string(), None);
440+
assert_eq!(
441+
&col_doc_no_doc.to_string(),
442+
&"Column Name: test\nNo Column Doc Found\n".to_string()
443+
);
428444
assert_eq!(col_doc.doc(), Some("comment"));
429445
assert_eq!(col_doc.name(), "test");
446+
assert_eq!(col_doc_no_doc.doc(), None);
447+
assert_eq!(col_doc_no_doc.name(), "test");
448+
let table_doc = TableDoc::new(
449+
Some("schema".to_string()),
450+
"table".to_string(),
451+
Some("table doc".to_string()),
452+
vec![col_doc],
453+
);
454+
let table_doc_no_doc = TableDoc::new(None, "table".to_string(), None, vec![col_doc_no_doc]);
455+
assert_eq!(table_doc.name(), "table");
456+
assert_eq!(table_doc.schema(), Some("schema"));
457+
assert_eq!(
458+
table_doc.to_string(),
459+
"Table Schema: schema\nTable Name: table\nTable Doc: table doc\nTable Column Docs: \n Column Name: test\nColumn Doc: comment\n"
460+
);
461+
assert_eq!(table_doc_no_doc.schema(), None);
462+
assert_eq!(table_doc_no_doc.name(), "table");
463+
assert_eq!(
464+
table_doc_no_doc.to_string(),
465+
"No Table Schema\nTable Name: table\nNo Table Doc\nTable Column Docs: \n Column Name: test\nNo Column Doc Found\n"
466+
);
467+
}
468+
469+
fn ident(v: &str) -> Ident {
470+
Ident { value: v.to_string(), quote_style: None, span: Span::empty() }
471+
}
472+
473+
fn func_part(name: &str) -> ObjectNamePart {
474+
ObjectNamePart::Function(ObjectNamePartFunction { name: ident(name), args: vec![] })
475+
}
476+
477+
#[test]
478+
fn schema_and_table_errors_when_no_identifier_parts() {
479+
let name = ObjectName(vec![func_part("now")]);
480+
481+
let err = match schema_and_table(&name) {
482+
Ok(v) => panic!("expected Err(DocError::InvalidObjectName), got Ok({v:?})"),
483+
Err(e) => e,
484+
};
485+
486+
match err {
487+
DocError::InvalidObjectName { message, .. } => {
488+
assert_eq!(message, "ObjectName had no identifier parts");
489+
}
490+
other => panic!("unexpected error: {other:?}"),
491+
}
492+
}
493+
494+
#[test]
495+
fn schema_and_table_single_identifier() {
496+
let name = ObjectName(vec![ObjectNamePart::Identifier(ident("users"))]);
497+
498+
let (schema, table) = match schema_and_table(&name) {
499+
Ok(v) => v,
500+
Err(e) => panic!("unexpected error: {e:?}"),
501+
};
502+
503+
assert_eq!(schema, None);
504+
assert_eq!(table, "users");
505+
}
506+
507+
#[test]
508+
fn schema_and_table_schema_and_table_with_function_ignored()
509+
-> Result<(), Box<dyn std::error::Error>> {
510+
let name = ObjectName(vec![
511+
ObjectNamePart::Identifier(ident("catalog")),
512+
ObjectNamePart::Identifier(ident("public")),
513+
func_part("some_func"),
514+
ObjectNamePart::Identifier(ident("orders")),
515+
]);
516+
517+
let (schema, table) = schema_and_table(&name)?;
518+
assert_eq!(schema, Some("public".to_string()));
519+
assert_eq!(table, "orders");
520+
Ok(())
521+
}
522+
523+
struct FailOnNthWrite {
524+
fail_at: usize,
525+
writes: usize,
526+
sink: String,
527+
}
528+
529+
impl FailOnNthWrite {
530+
fn new(fail_at: usize) -> Self {
531+
Self { fail_at, writes: 0, sink: String::new() }
532+
}
533+
}
534+
535+
impl fmt::Write for FailOnNthWrite {
536+
fn write_str(&mut self, s: &str) -> fmt::Result {
537+
self.writes += 1;
538+
if self.writes == self.fail_at {
539+
return Err(fmt::Error);
540+
}
541+
self.sink.push_str(s);
542+
Ok(())
543+
}
544+
}
545+
546+
fn run_fail_at<T: fmt::Display>(v: &T, fail_at: usize) -> Result<(), fmt::Error> {
547+
let mut w = FailOnNthWrite::new(fail_at);
548+
fmt::write(&mut w, format_args!("{v}"))
549+
}
550+
551+
fn count_writes<T: fmt::Display>(v: &T) -> usize {
552+
let mut w = FailOnNthWrite { fail_at: usize::MAX, writes: 0, sink: String::new() };
553+
// We don't care if this errors (it shouldn't with fail_at=MAX), we only want the write count.
554+
let _ = fmt::write(&mut w, format_args!("{v}"));
555+
w.writes
556+
}
557+
558+
#[test]
559+
fn display_propagates_every_question_mark_path_for_column_and_table() {
560+
let col_with_doc = ColumnDoc::new("col_a".into(), Some("doc".into()));
561+
let col_without_doc = ColumnDoc::new("col_b".into(), None);
562+
563+
let table = TableDoc::new(
564+
Some("public".into()),
565+
"users".into(),
566+
Some("table doc".into()),
567+
vec![col_with_doc.clone(), col_without_doc],
568+
);
569+
570+
let col_writes = count_writes(&col_with_doc);
571+
let table_writes = count_writes(&table);
572+
573+
for i in 1..=col_writes {
574+
assert!(
575+
run_fail_at(&col_with_doc, i).is_err(),
576+
"ColumnDoc should error when failing at write #{i} (total writes {col_writes})"
577+
);
578+
}
579+
580+
for i in 1..=table_writes {
581+
assert!(
582+
run_fail_at(&table, i).is_err(),
583+
"TableDoc should error when failing at write #{i} (total writes {table_writes})"
584+
);
585+
}
430586
}
431587
}

0 commit comments

Comments
 (0)