Решение на Logging от Димитър Михайлов
Към профила на Димитър Михайлов
Резултати
- 13 точки от тестове
- 0 бонус точки
- 13 точки общо
- 10 успешни тест(а)
- 5 неуспешни тест(а)
Код
Лог от изпълнението
Compiling solution v0.1.0 (/tmp/d20190123-22631-14ux4a8/solution) warning: function is never used: `main` --> src/lib.rs:185:1 | 185 | fn main() { | ^^^^^^^^^ | = note: #[warn(dead_code)] on by default Finished dev [unoptimized + debuginfo] target(s) in 4.94s Running target/debug/deps/solution-2e785d603b538f71 running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Running target/debug/deps/solution_test-29808948fb50ed3a running 15 tests test solution_test::test_automatic_flushing_when_buffer_limit_is_reached ... ok test solution_test::test_automatic_flushing_when_zero_buffer_limit ... FAILED test solution_test::test_basic_log ... ok test solution_test::test_basic_push ... ok test solution_test::test_cloning_a_logger_shares_a_buffer ... ok test solution_test::test_cloning_a_logger_shares_their_io ... ok test solution_test::test_erroring_io ... FAILED test solution_test::test_flushing_the_buffer ... ok test solution_test::test_logger_combinations ... ok test solution_test::test_multilogger_logs_and_flushes_when_needed ... FAILED test solution_test::test_multilogger_logs_to_several_ios ... ok test solution_test::test_reordering_logs_in_buffer ... ok test solution_test::test_reordering_logs_in_io ... ok test solution_test::test_scoped_logger ... FAILED test solution_test::test_scoped_logger_with_a_string_tag ... FAILED failures: ---- solution_test::test_automatic_flushing_when_zero_buffer_limit stdout ---- thread 'solution_test::test_automatic_flushing_when_zero_buffer_limit' panicked at 'assertion failed: `(left == right)` left: `1`, right: `0`', tests/solution_test.rs:210:9 note: Run with `RUST_BACKTRACE=1` for a backtrace. ---- solution_test::test_erroring_io stdout ---- thread 'solution_test::test_erroring_io' panicked at 'Expected try_flush with an erroring IO to return an error', tests/solution_test.rs:340:9 ---- solution_test::test_multilogger_logs_and_flushes_when_needed stdout ---- thread 'solution_test::test_multilogger_logs_and_flushes_when_needed' panicked at 'assertion failed: `(left == right)` left: `3`, right: `0`', tests/solution_test.rs:288:9 ---- solution_test::test_scoped_logger stdout ---- thread 'solution_test::test_scoped_logger' panicked at 'assertion failed: `(left == right)` left: `"[First] One\n[Second] Two\n[Second] Three\n[First] Four\n[First] One\n[Second] Two\n[Second] Three\n[First] Four\n"`, right: `"[First] One\n[Second] Two\n[Second] Three\n[First] Four\n"`', tests/solution_test.rs:315:5 ---- solution_test::test_scoped_logger_with_a_string_tag stdout ---- thread 'solution_test::test_scoped_logger_with_a_string_tag' panicked at 'assertion failed: `(left == right)` left: `""`, right: `"[First] Test\n"`', tests/solution_test.rs:329:5 failures: solution_test::test_automatic_flushing_when_zero_buffer_limit solution_test::test_erroring_io solution_test::test_multilogger_logs_and_flushes_when_needed solution_test::test_scoped_logger solution_test::test_scoped_logger_with_a_string_tag test result: FAILED. 10 passed; 5 failed; 0 ignored; 0 measured; 0 filtered out error: test failed, to rerun pass '--test solution_test'
История (6 версии и 11 коментара)
Димитър качи решение на 18.12.2018 00:18 (преди почти 7 години)
Димитър качи решение на 18.12.2018 00:20 (преди почти 7 години)
Димитър качи решение на 18.12.2018 00:21 (преди почти 7 години)
Не успях да го направя да share-ват един buffer и out. :С
трябваше да коментирам всичко тук, за да предам задачата. self.logger.into_iter() ми дава cannot move out of borrowed content. Не мога да го измисля, направо ми гръмна главата :D
Без MultiLogger
не ти се компилира домашното с тестовете, така че погрижи се да оправиш проблема, иначе оставаш с 0 точки. Дори да оставиш MultiLogger
нещата с unimplemented!()
би било по-добре, но най-добре просто дебъгни проблема. Не забравяй, че имаме и базов тест, с който можеш да провериш дали ще ти се компилира решението поне, виж новината: https://fmi.rust-lang.bg/announcements/5
Иначе, погледни внимателно дефиницията на into_iter
и помисли какво прави: https://doc.rust-lang.org/std/iter/trait.IntoIterator.html#tymethod.into_iter. Помисли си и какво значи грешката "cannot move out of borrowed content". Кое е "borrowed", и защо нещо се опитва да "move"-не от него?
Димитър качи решение на 18.12.2018 10:59 (преди почти 7 години)
Решението ти се компилира в момента, така че внимавай с промените :). Имайки това предвид, помисли си дали сортираш правилно буфера. Прочети инструкцията и си помисли какъв тест можеш да напишеш, за да провериш.
logger.push(now + Duration::from_millis(2), "Test2"); logger.push(now + Duration::from_millis(1), "Test1"); assert_eq!(logger.buffered_entries(), vec!["Test1", "Test2"]);
това не е ли тестът, който проверява сортирането? В случая първо вкарваме Test2 после Test1, но Test1 е преди Test2, гледайки Duration-a. И buffered_entries() ги изкарва в правилния ред, а именно Test1, Test2
Димитър качи решение на 18.12.2018 14:08 (преди почти 7 години)
Като се замисля сорт-а може би работеше, защото Test1 излиза преди Test2 заради цифрите. Промених го на sort_by и му казах да compare-ва Instant частта от tuple-a
Да, това се надявах да осъзнаеш :). Тестовете, които сме ви дали, са доста прости, и са по един тест на казус. Добре е човек да напише поне два теста за нещо, с различни данни, защото единия може да минава на късмет.
Иначе, един начин да избегнеш това е да съхраняваш (time, text)
вместо (text, time)
. Така сортирането ще ги подреди по първия елемент, и само ако първите са едни и същи, ще сортира и вторите азбучно (не сме ви казали какво трябва да се случи ако времената са едни и същи, така че няма значение за решението).
Друг метод е вместо tuple да си направиш собствен тип, примерно Entry
, и да му дефинираш Ord
. Може да погледнеш моето решение, макар че в него аз съм го имплементирал малко наобратно, понеже използвам BinaryHeap
вместо Vec
:).
Този метод не беше идеята винаги да връща успех :). Идеята беше той да върши работата и да връща грешка, ако се случи грешка, а flush
да я логва и продължава. И сме написали тест, който да проверява това. Може да разгледаш тестовете тук: https://github.com/fmi/rust-homework/blob/master/03/test_full.rs
Метода expect
ще гръмне, ако писането е невъзможно, а очаквахме да се напечата проблема на stderr и да се продължи програмата.
Не би трябвало да е нужно да викаш as_mut()
тук, понеже Box
-а е "прозрачен" откъм методи -- извикването на метод вика deref
или deref_mut
когато е нужно и свежда box-а до reference.
Форматирането на низа можеше и да е по-просто като че ли :). И без малко особено-именувани променливи като a, b, и c. Аз съм го направил така:
self.base_logger.push(time, &format!("[{}] {}", self.tag, text));
А метода log
няма нужда да повтаря кода. Можеше даже да е имплементиран в самия trait:
fn log(&mut self, text: &str) {
self.push(Instant::now(), text)
}
Казвали сме го и друг път, но: почвай по-отрано с домашното. Дай си време да напишеш малко по-интересни тестове, да експериментираш, да го огледаш за подобрения.
Не успях да го направя да share-ват един buffer и out. :С
Решението ти се компилира в момента, така че внимавай с промените :). Имайки това предвид, помисли си дали сортираш правилно буфера. Прочети инструкцията и си помисли какъв тест можеш да напишеш, за да провериш.
logger.push(now + Duration::from_millis(2), "Test2"); logger.push(now + Duration::from_millis(1), "Test1"); assert_eq!(logger.buffered_entries(), vec!["Test1", "Test2"]);
това не е ли тестът, който проверява сортирането? В случая първо вкарваме Test2 после Test1, но Test1 е преди Test2, гледайки Duration-a. И buffered_entries() ги изкарва в правилния ред, а именно Test1, Test2
Като се замисля сорт-а може би работеше, защото Test1 излиза преди Test2 заради цифрите. Промених го на sort_by и му казах да compare-ва Instant частта от tuple-a
Да, това се надявах да осъзнаеш :). Тестовете, които сме ви дали, са доста прости, и са по един тест на казус. Добре е човек да напише поне два теста за нещо, с различни данни, защото единия може да минава на късмет.
Иначе, един начин да избегнеш това е да съхраняваш
(time, text)
вместо(text, time)
. Така сортирането ще ги подреди по първия елемент, и само ако първите са едни и същи, ще сортира и вторите азбучно (не сме ви казали какво трябва да се случи ако времената са едни и същи, така че няма значение за решението).Друг метод е вместо tuple да си направиш собствен тип, примерно
Entry
, и да му дефинирашOrd
. Може да погледнеш моето решение, макар че в него аз съм го имплементирал малко наобратно, понеже използвамBinaryHeap
вместоVec
:).Този метод не беше идеята винаги да връща успех :). Идеята беше той да върши работата и да връща грешка, ако се случи грешка, а
flush
да я логва и продължава. И сме написали тест, който да проверява това. Може да разгледаш тестовете тук: https://github.com/fmi/rust-homework/blob/master/03/test_full.rsМетода
expect
ще гръмне, ако писането е невъзможно, а очаквахме да се напечата проблема на stderr и да се продължи програмата.Не би трябвало да е нужно да викаш
as_mut()
тук, понежеBox
-а е "прозрачен" откъм методи -- извикването на метод викаderef
илиderef_mut
когато е нужно и свежда box-а до reference.Форматирането на низа можеше и да е по-просто като че ли :). И без малко особено-именувани променливи като a, b, и c. Аз съм го направил така:
А метода
log
няма нужда да повтаря кода. Можеше даже да е имплементиран в самия trait: