Skip to content

Commit

Permalink
fix: Improve the accuracy of the coverage report.
Browse files Browse the repository at this point in the history
- Ignore trailing '()' characters in function names when reporting coverage.
- Only track functions that match a function in the header file of interest as implemented.
- Mark the uenum::uloc_open_keywords as deprecated, copy the implementation into the uloc crate and copy the test that was in the uloc crate into the uenum crate so that it is still protected by a test even though deprecated.
  • Loading branch information
clydegerber authored and filmil committed Nov 10, 2023
1 parent be8d019 commit 684e1be
Show file tree
Hide file tree
Showing 10 changed files with 77 additions and 132 deletions.
123 changes: 68 additions & 55 deletions build/showprogress.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,86 +29,99 @@ C_API_HEADER_NAMES=(

ICU_INCLUDE_PATH="$(icu-config --cppflags-searchpath | sed -e 's/-I//' | sed -e 's/ //g')"

for header_basename in ${C_API_HEADER_NAMES[@]}; do
header_fullname="${ICU_INCLUDE_PATH}/unicode/${header_basename}.h"
echo $header_basename: $header_fullname
ctags -x --c-kinds=fp $header_fullname | sed -e 's/ .*$//' \
| grep -v U_DEFINE | sort | uniq \
> "${TOP_DIR}/coverage/${header_basename}_all.txt"

# Extracts all mentions of functions such as "utext_close" for example from
# rust docs of the form "/// Implements `utext_close` ... ". This is
# simplistic but quite enough with a little bit of care.
find . -path "*rust_icu_${header_basename}/src/*.rs" | \
xargs grep "/// Implements \`" | sed -e 's/.*`\(.*\)`.*$/\1/' | sed -e 's/\(.*\)()$/\1/' | \
sort | uniq > "${TOP_DIR}/coverage/${header_basename}_implemented.txt"
done

# Now, write a report out. Again, simplistic, but gets the job done.
# Write a report out as we read the data.

REPORT_FILE="${TOP_DIR}/coverage/report.md"
cat <<EOF > "${REPORT_FILE}"
REPORT_FILE_HEADER="${TOP_DIR}/coverage/report_header.md"
REPORT_FILE_DETAIL="${TOP_DIR}/coverage/report_detail.md"
cat <<EOF > "${REPORT_FILE_HEADER}"
# Implementation coverage report
| Header | Implemented |
| ------ | ----------- |
EOF
for header_basename in ${C_API_HEADER_NAMES[@]}; do
total_functions="$(cat "${TOP_DIR}"/coverage/${header_basename}_all.txt | wc -l)"
implemented_functions="$(cat "${TOP_DIR}"/coverage/${header_basename}_implemented.txt | wc -l)"
printf "| \`%s.h\` | %s / %s | \n" ${header_basename} ${implemented_functions} ${total_functions} >> "${REPORT_FILE}"
done

cat <<EOF >>"${REPORT_FILE}"
cat <<EOF >>"${REPORT_FILE_DETAIL}"
# Unimplemented functions per header
EOF
for header_basename in ${C_API_HEADER_NAMES[@]}; do
cat <<EOF >>"${REPORT_FILE}"
# Header: \`${header_basename}.h\`
| Unimplemented | Implemented |
| ------------- | ----------- |
EOF
all=`cat ${TOP_DIR}/coverage/${header_basename}_all.txt | sort -fs`
implemented=`cat "${TOP_DIR}/coverage/${header_basename}_implemented.txt" | sort -fs`
for fun in ${implemented}; do
echo "| | \`${fun}\` |" >>"${REPORT_FILE}"
done

unimplemented="$(comm -23 \
"${TOP_DIR}/coverage/${header_basename}_all.txt" \
"${TOP_DIR}/coverage/${header_basename}_implemented.txt" | sort -fs | uniq)"
for fun in ${unimplemented}; do
echo "| \`${fun}\` | |" >>"${REPORT_FILE}"
for header_basename in ${C_API_HEADER_NAMES[@]}; do
: > "${TOP_DIR}/coverage/${header_basename}_all.txt"
: > "${TOP_DIR}/coverage/${header_basename}_implemented.txt"
header_fullname="${ICU_INCLUDE_PATH}/unicode/${header_basename}.h"
all=$(ctags -x --c-kinds=fp $header_fullname | sed -e 's/ .*$//' \
| grep -v U_DEFINE | sort -fs | uniq)
for fn in ${all}; do
printf "%s\n" ${fn} >> "${TOP_DIR}/coverage/${header_basename}_all.txt"
done

total_cnt=`echo ${all} | wc -w`
implemented_cnt=`echo ${implemented} | wc -w`
unimplemented_cnt=`echo ${unimplemented} | wc -w`
computed_total_cnt=`expr ${unimplemented_cnt} + ${implemented_cnt}`
if [ ${computed_total_cnt} -ne ${total_cnt} ]
then
printf "Warning: Implemented + Unimplemented != Total\n" >> ${REPORT_FILE}
printf "Total: %s Implemented: %s Unimplemented: %s\n" ${total_cnt} ${implemented_cnt} ${unimplemented_cnt} >> "${REPORT_FILE}"
for impl_fn in ${implemented}; do
found="false"
# Extracts all mentions of functions such as "utext_close" for example from
# rust docs of the form "/// Implements `utext_close` ... ". This is
# simplistic but quite enough with a little bit of care.
files=`find . -path "*rust_icu_${header_basename}/src/*.rs"`
impl_fns=""
unimpl_fns=""
for file in ${files}; do
echo $header_basename: $header_fullname ${file}
found_fns="$(grep "/// Implements \`" ${file} | sed -e 's/.*`\(.*\)`.*$/\1/' | sed -e 's/\(.*\)()$/\1/' | sort -fs | uniq)"
# Match the extracted function to a function in the header being processed
# (in case the "/// Implements `" comment is used in another context)
for impl_fn in ${found_fns}; do
for all_fn in ${all}; do
if [ ${impl_fn} = ${all_fn} ]
then
found="true"
impl_fns="${impl_fns} ${impl_fn}"
break
fi
done
if [ "false" = ${found} ]
done
done
# Sort again in case we process multiple source files
impl_fns="$(echo ${impl_fns} | sort -fs | uniq)"
for impl_fn in ${impl_fns}; do
printf "%s\n" ${impl_fn} >> "${TOP_DIR}/coverage/${header_basename}_implemented.txt"
done
unimpl_fns=""
for all_fn in ${all}; do
found="false"
for impl_fn in ${impl_fns}; do
if [ ${impl_fn} = ${all_fn} ]
then
printf "Function %s was designated as implemented but not found in the API\n" ${impl_fn} >> "${REPORT_FILE}"
found="true"
break
fi
done
fi
if [ "false" = ${found} ]
then
unimpl_fns="${unimpl_fns} ${all_fn}"
fi
done

total_functions=$(echo ${all} | wc -w)
implemented_functions=$(echo ${impl_fns} | wc -w)
printf "| \`%s.h\` | %s / %s | \n" ${header_basename} ${implemented_functions} ${total_functions} >> "${REPORT_FILE_HEADER}"

cat <<EOF >>"${REPORT_FILE_DETAIL}"
# Header: \`${header_basename}.h\`
| Unimplemented | Implemented |
| ------------- | ----------- |
EOF
for impl_fn in ${impl_fns}; do
printf "| | \`%s\` |\n" ${impl_fn} >>"${REPORT_FILE_DETAIL}"
done

for fun in ${unimpl_fns}; do
printf "| \`%s\` | |\n" ${fun} >>"${REPORT_FILE_DETAIL}"
done

sort -fs -o "${TOP_DIR}/coverage/${header_basename}_all.txt" "${TOP_DIR}/coverage/${header_basename}_all.txt"
sort -fs -o "${TOP_DIR}/coverage/${header_basename}_implemented.txt" "${TOP_DIR}/coverage/${header_basename}_implemented.txt"
done

cat ${REPORT_FILE_HEADER} ${REPORT_FILE_DETAIL} > ${REPORT_FILE}
rm ${REPORT_FILE_HEADER}
rm ${REPORT_FILE_DETAIL}

64 changes: 7 additions & 57 deletions coverage/report.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@
| `ubrk.h` | 19 / 23 |
| `ucal.h` | 15 / 47 |
| `ucol.h` | 8 / 51 |
| `udat.h` | 10 / 38 |
| `udata.h` | 4 / 8 |
| `uenum.h` | 7 / 8 |
| `udat.h` | 5 / 38 |
| `udata.h` | 2 / 8 |
| `uenum.h` | 3 / 8 |
| `uformattable.h` | 6 / 13 |
| `ulistformatter.h` | 2 / 8 |
| `uloc.h` | 28 / 42 |
| `umsg.h` | 6 / 20 |
| `umsg.h` | 5 / 20 |
| `unum.h` | 14 / 32 |
| `unumberformatter.h` | 7 / 6 |
| `unumberformatter.h` | 3 / 6 |
| `upluralrules.h` | 3 / 8 |
| `ustring.h` | 3 / 61 |
| `utext.h` | 3 / 28 |
| `ustring.h` | 2 / 61 |
| `utext.h` | 2 / 28 |
| `utrans.h` | 10 / 20 |
| `unorm2.h` | 8 / 22 |
# Unimplemented functions per header
Expand Down Expand Up @@ -162,11 +162,6 @@

| Unimplemented | Implemented |
| ------------- | ----------- |
| | `UDateFormat` |
| | `UDateTimePatternGenerator` |
| | `udatpg_clone` |
| | `udatpg_getBestPattern` |
| | `udatpg_open` |
| | `udat_close` |
| | `udat_format` |
| | `udat_open` |
Expand Down Expand Up @@ -205,41 +200,24 @@
| `udat_toPatternRelativeDate` | |
| `udat_toPatternRelativeTime` | |
| `udat_unregisterOpener` | |
Warning: Implemented + Unimplemented != Total
Total: 38 Implemented: 10 Unimplemented: 33
Function UDateFormat was designated as implemented but not found in the API
Function UDateTimePatternGenerator was designated as implemented but not found in the API
Function udatpg_clone was designated as implemented but not found in the API
Function udatpg_getBestPattern was designated as implemented but not found in the API
Function udatpg_open was designated as implemented but not found in the API

# Header: `udata.h`

| Unimplemented | Implemented |
| ------------- | ----------- |
| | `UDataMemory` |
| | `udata_open` |
| | `udata_setCommonData` |
| | `u_setDataDirectory` |
| `udata_close` | |
| `udata_getInfo` | |
| `udata_getMemory` | |
| `udata_openChoice` | |
| `udata_setAppData` | |
| `udata_setFileAccess` | |
Warning: Implemented + Unimplemented != Total
Total: 8 Implemented: 4 Unimplemented: 6
Function UDataMemory was designated as implemented but not found in the API
Function u_setDataDirectory was designated as implemented but not found in the API

# Header: `uenum.h`

| Unimplemented | Implemented |
| ------------- | ----------- |
| | `ucal_openCountryTimeZones` |
| | `ucal_openTimeZoneIDEnumeration` |
| | `ucal_openTimeZones` |
| | `UEnumeration` |
| | `uenum_close` |
| | `uenum_next` |
| | `uenum_openCharStringsEnumeration` |
Expand All @@ -248,12 +226,6 @@ Function u_setDataDirectory was designated as implemented but not found in the A
| `uenum_openUCharStringsEnumeration` | |
| `uenum_reset` | |
| `uenum_unext` | |
Warning: Implemented + Unimplemented != Total
Total: 8 Implemented: 7 Unimplemented: 5
Function ucal_openCountryTimeZones was designated as implemented but not found in the API
Function ucal_openTimeZoneIDEnumeration was designated as implemented but not found in the API
Function ucal_openTimeZones was designated as implemented but not found in the API
Function UEnumeration was designated as implemented but not found in the API

# Header: `uformattable.h`

Expand Down Expand Up @@ -337,7 +309,6 @@ Function UEnumeration was designated as implemented but not found in the API

| Unimplemented | Implemented |
| ------------- | ----------- |
| | `UMessageFormat` |
| | `umsg_clone` |
| | `umsg_close` |
| | `umsg_format` |
Expand All @@ -358,9 +329,6 @@ Function UEnumeration was designated as implemented but not found in the API
| `u_vformatMessageWithError` | |
| `u_vparseMessage` | |
| `u_vparseMessageWithError` | |
Warning: Implemented + Unimplemented != Total
Total: 20 Implemented: 6 Unimplemented: 15
Function UMessageFormat was designated as implemented but not found in the API

# Header: `unum.h`

Expand Down Expand Up @@ -406,19 +374,9 @@ Function UMessageFormat was designated as implemented but not found in the API
| | `unumf_formatDecimal` |
| | `unumf_openForSkeletonAndLocale` |
| | `unumf_openForSkeletonAndLocaleWithError` |
| | `unumf_openResult` |
| | `unumf_resultGetAllFieldPositions` |
| | `unumf_resultNextFieldPosition` |
| | `unumf_resultToString` |
| `unumf_close` | |
| `unumf_formatDouble` | |
| `unumf_formatInt` | |
Warning: Implemented + Unimplemented != Total
Total: 6 Implemented: 7 Unimplemented: 3
Function unumf_openResult was designated as implemented but not found in the API
Function unumf_resultGetAllFieldPositions was designated as implemented but not found in the API
Function unumf_resultNextFieldPosition was designated as implemented but not found in the API
Function unumf_resultToString was designated as implemented but not found in the API

# Header: `upluralrules.h`

Expand All @@ -437,7 +395,6 @@ Function unumf_resultToString was designated as implemented but not found in the

| Unimplemented | Implemented |
| ------------- | ----------- |
| | `UChar*` |
| | `u_strFromUTF8` |
| | `u_strToUTF8` |
| `u_austrcpy` | |
Expand Down Expand Up @@ -499,17 +456,13 @@ Function unumf_resultToString was designated as implemented but not found in the
| `u_uastrncpy` | |
| `u_unescape` | |
| `u_unescapeAt` | |
Warning: Implemented + Unimplemented != Total
Total: 61 Implemented: 3 Unimplemented: 59
Function UChar* was designated as implemented but not found in the API

# Header: `utext.h`

| Unimplemented | Implemented |
| ------------- | ----------- |
| | `utext_clone` |
| | `utext_close` |
| | `utext_open` |
| `utext_char32At` | |
| `utext_copy` | |
| `utext_current32` | |
Expand All @@ -536,9 +489,6 @@ Function UChar* was designated as implemented but not found in the API
| `utext_replace` | |
| `utext_setNativeIndex` | |
| `utext_setup` | |
Warning: Implemented + Unimplemented != Total
Total: 28 Implemented: 3 Unimplemented: 26
Function utext_open was designated as implemented but not found in the API

# Header: `utrans.h`

Expand Down
5 changes: 0 additions & 5 deletions coverage/udat_implemented.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
UDateFormat
UDateTimePatternGenerator
udatpg_clone
udatpg_getBestPattern
udatpg_open
udat_close
udat_format
udat_open
Expand Down
2 changes: 0 additions & 2 deletions coverage/udata_implemented.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
UDataMemory
udata_open
udata_setCommonData
u_setDataDirectory
4 changes: 0 additions & 4 deletions coverage/uenum_implemented.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
ucal_openCountryTimeZones
ucal_openTimeZoneIDEnumeration
ucal_openTimeZones
UEnumeration
uenum_close
uenum_next
uenum_openCharStringsEnumeration
1 change: 0 additions & 1 deletion coverage/umsg_implemented.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
UMessageFormat
umsg_clone
umsg_close
umsg_format
Expand Down
4 changes: 0 additions & 4 deletions coverage/unumberformatter_implemented.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
unumf_formatDecimal
unumf_openForSkeletonAndLocale
unumf_openForSkeletonAndLocaleWithError
unumf_openResult
unumf_resultGetAllFieldPositions
unumf_resultNextFieldPosition
unumf_resultToString
1 change: 0 additions & 1 deletion coverage/ustring_implemented.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
UChar*
u_strFromUTF8
u_strToUTF8
1 change: 0 additions & 1 deletion coverage/utext_implemented.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
utext_clone
utext_close
utext_open
4 changes: 2 additions & 2 deletions rust_icu_uloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ impl ULoc {
.map(|result| result.unwrap())
}

/// Implementation of `icu::Locale::getUnicodeKeywords()` from the C++ API.
/// Implements `icu::Locale::getUnicodeKeywords()` from the C++ API.
pub fn unicode_keywords(&self) -> impl Iterator<Item = String> {
self.keywords().filter_map(|s| to_unicode_locale_key(&s))
}
Expand All @@ -463,7 +463,7 @@ impl ULoc {
.map(|value| if value.is_empty() { None } else { Some(value) })
}

/// Implementation of `icu::Locale::getUnicodeKeywordValue()` from the C++ API.
/// Implements `icu::Locale::getUnicodeKeywordValue()` from the C++ API.
pub fn unicode_keyword_value(
&self,
unicode_keyword: &str,
Expand Down

0 comments on commit 684e1be

Please sign in to comment.