run.sh 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. #!/usr/bin/env bash
  2. if [ -z "${BASH_VERSION:-}" ]; then
  3. echo "This script requires bash, not sh. Re-run it as: bash $0 $*" 1>&2
  4. exec bash "$0" "$@"
  5. fi
  6. set -u
  7. export NODE_NO_WARNINGS=1
  8. cd "$(dirname "$0")/.."
  9. GREEN=$'\e[32m'
  10. RED=$'\e[31m'
  11. YELLOW=$'\e[33m'
  12. BOLD=$'\e[1m'
  13. RESET=$'\e[0m'
  14. SSB_DIR="$HOME/.ssb"
  15. SSB_BACKUP=""
  16. ASSUME_YES=0
  17. RESTORE=0
  18. SKIP_ISOLATION=0
  19. CLEAN_ALL=0
  20. SEED=0
  21. DUMMY_ONLY=0
  22. for arg in "$@"; do
  23. case "$arg" in
  24. -y|--yes) ASSUME_YES=1 ;;
  25. --restore) RESTORE=1 ;;
  26. --no-isolation) SKIP_ISOLATION=1 ;;
  27. --seed) SEED=1 ;;
  28. dummy|--dummy) SEED=1; DUMMY_ONLY=1 ;;
  29. clean-all|--clean-all) CLEAN_ALL=1 ;;
  30. -h|--help)
  31. cat <<EOF
  32. Usage: $0 [options]
  33. Options:
  34. -y, --yes skip confirmation prompt
  35. --restore restore your original ~/.ssb on exit (DESTROYS test data)
  36. Default: keep the test ~/.ssb so you can boot oasis and
  37. visually inspect what the tests produced.
  38. --no-isolation run tests against current ~/.ssb (DANGEROUS — may conflict)
  39. --seed after all mock tests pass, write dummy content to the
  40. isolated ~/.ssb via the REAL SSB models (so you can boot
  41. oasis and visually inspect modules with realistic data).
  42. dummy skip tests AND isolation; publish real content into your
  43. running oasis (~/.ssb) so the network gets filled with
  44. dummy data you can immediately see in the browser. Requires
  45. oasis to be running (sh oasis.sh) in another terminal.
  46. clean-all delete all test reports in results/ AND the test ~/.ssb,
  47. then exit (does NOT run tests). If a backup exists, it is
  48. restored first so you don't lose your real data.
  49. -h, --help this message
  50. Each run generates test/results/unit_test_<timestamp>.md
  51. EOF
  52. exit 0
  53. ;;
  54. esac
  55. done
  56. if [ "$CLEAN_ALL" = "1" ]; then
  57. echo "${YELLOW}${BOLD}clean-all:${RESET}"
  58. latest_backup=$(ls -dt "$HOME"/.ssb-bak-* 2>/dev/null | head -1)
  59. if [ -n "$latest_backup" ] && [ -d "$SSB_DIR" ]; then
  60. echo " found backup: $latest_backup"
  61. if [ "$ASSUME_YES" != "1" ]; then
  62. if [ ! -t 0 ]; then
  63. echo "${RED}stdin is not a TTY; refusing to prompt. Pass --yes to skip prompt.${RESET}"
  64. exit 2
  65. fi
  66. read -r -p " remove test ~/.ssb and restore your original from latest backup? [y/N] " ans
  67. case "$ans" in
  68. y|Y|yes|YES) ;;
  69. *) echo " aborted."; exit 1 ;;
  70. esac
  71. fi
  72. rm -rf "$SSB_DIR"
  73. mv "$latest_backup" "$SSB_DIR" && echo " ${GREEN}~/.ssb restored from $latest_backup${RESET}"
  74. elif [ -n "$latest_backup" ] && [ ! -d "$SSB_DIR" ]; then
  75. mv "$latest_backup" "$SSB_DIR" && echo " ${GREEN}~/.ssb restored from $latest_backup${RESET}"
  76. elif [ -d "$SSB_DIR" ]; then
  77. if [ "$ASSUME_YES" != "1" ]; then
  78. if [ ! -t 0 ]; then
  79. echo "${RED}stdin is not a TTY; refusing to prompt. Pass --yes to skip prompt.${RESET}"
  80. exit 2
  81. fi
  82. read -r -p " no backup found. Delete current ~/.ssb anyway? [y/N] " ans
  83. case "$ans" in
  84. y|Y|yes|YES) rm -rf "$SSB_DIR" && echo " ${GREEN}~/.ssb deleted.${RESET}" ;;
  85. *) echo " ~/.ssb left intact." ;;
  86. esac
  87. else
  88. rm -rf "$SSB_DIR" && echo " ${GREEN}~/.ssb deleted.${RESET}"
  89. fi
  90. else
  91. echo " no ~/.ssb to clean."
  92. fi
  93. bak_count=$(ls -d "$HOME"/.ssb-bak-* 2>/dev/null | wc -l)
  94. if [ "$bak_count" -gt 0 ]; then
  95. for b in "$HOME"/.ssb-bak-*; do
  96. [ -e "$b" ] && rm -rf "$b" && echo " removed: $b"
  97. done
  98. fi
  99. if [ -d "test/results" ]; then
  100. n=$(ls test/results/unit_test_*.md 2>/dev/null | wc -l)
  101. rm -f test/results/unit_test_*.md
  102. echo " ${GREEN}removed $n report(s) from test/results/${RESET}"
  103. fi
  104. echo "${GREEN}clean-all done.${RESET}"
  105. exit 0
  106. fi
  107. isolate_ssb() {
  108. if [ "$SKIP_ISOLATION" = "1" ]; then
  109. echo "${YELLOW}⚠ skipping ~/.ssb isolation (--no-isolation set). Tests may conflict with running oasis.${RESET}"
  110. return
  111. fi
  112. if [ ! -e "$SSB_DIR" ] && [ ! -L "$SSB_DIR" ]; then
  113. return
  114. fi
  115. local ts=$(date +%Y%m%d_%H%M%S)
  116. SSB_BACKUP="${SSB_DIR}-bak-${ts}"
  117. echo ""
  118. echo "${YELLOW}${BOLD}⚠ WARNING${RESET}"
  119. echo "${YELLOW}This will move your current ${BOLD}${SSB_DIR}${RESET}${YELLOW} → ${BOLD}${SSB_BACKUP}${RESET}"
  120. echo "${YELLOW}and create a fresh empty ${SSB_DIR} for the tests.${RESET}"
  121. echo "${YELLOW}On exit the test ~/.ssb is KEPT (visual inspection); your original stays at the backup path.${RESET}"
  122. echo "${YELLOW}If oasis is currently running, STOP IT FIRST.${RESET}"
  123. if [ "$ASSUME_YES" != "1" ]; then
  124. if [ ! -t 0 ]; then
  125. echo "${RED}stdin is not a TTY; refusing to prompt. Pass --yes to skip prompt.${RESET}"
  126. exit 2
  127. fi
  128. read -r -p "Continue? [y/N] " ans
  129. case "$ans" in
  130. y|Y|yes|YES) ;;
  131. *) echo "aborted."; exit 1 ;;
  132. esac
  133. fi
  134. mv "$SSB_DIR" "$SSB_BACKUP" || { echo "${RED}failed to move $SSB_DIR${RESET}"; exit 3; }
  135. mkdir -p "$SSB_DIR"
  136. echo "${GREEN}~/.ssb isolated → $SSB_BACKUP${RESET}"
  137. }
  138. restore_ssb() {
  139. if [ -z "$SSB_BACKUP" ]; then return; fi
  140. if [ "$RESTORE" != "1" ]; then
  141. echo ""
  142. echo "${YELLOW}Test ~/.ssb left in place for visual inspection.${RESET}"
  143. echo "${YELLOW} test data: $SSB_DIR${RESET}"
  144. echo "${YELLOW} your original: $SSB_BACKUP${RESET}"
  145. echo ""
  146. echo "${YELLOW}To boot oasis against the test data:${RESET} sh oasis.sh"
  147. echo "${YELLOW}To restore your original later:${RESET} rm -rf $SSB_DIR && mv $SSB_BACKUP $SSB_DIR"
  148. return
  149. fi
  150. echo ""
  151. echo "${YELLOW}Restoring ~/.ssb from backup...${RESET}"
  152. rm -rf "$SSB_DIR" 2>/dev/null
  153. mv "$SSB_BACKUP" "$SSB_DIR" && echo "${GREEN}~/.ssb restored.${RESET}" || echo "${RED}failed to restore — backup left at $SSB_BACKUP${RESET}"
  154. }
  155. trap restore_ssb EXIT INT TERM
  156. if [ "$DUMMY_ONLY" = "1" ]; then
  157. echo "${YELLOW}=== dummy mode: publishing real content to your running oasis (no isolation, no tests) ===${RESET}"
  158. echo "${YELLOW}Make sure oasis is currently running (sh oasis.sh) so the seed can connect via the local SSB socket.${RESET}"
  159. node test/seed.js
  160. rc=$?
  161. if [ "$rc" -eq 0 ]; then
  162. echo ""
  163. echo "${GREEN}Done. Refresh oasis in your browser to see the seeded content.${RESET}"
  164. else
  165. echo "${RED}seed.js exited with code $rc${RESET}"
  166. fi
  167. exit "$rc"
  168. fi
  169. isolate_ssb
  170. MODULES=(
  171. mods/crypto
  172. mods/tribes
  173. mods/sub-tribes
  174. mods/media/audios
  175. mods/media/videos
  176. mods/media/images
  177. mods/media/documents
  178. mods/media/bookmarks
  179. mods/forum
  180. mods/transfers
  181. mods/votes
  182. mods/events
  183. mods/tasks
  184. mods/chats
  185. mods/pads
  186. mods/maps
  187. mods/torrents
  188. mods/calendars
  189. mods/reports
  190. mods/market
  191. mods/jobs
  192. mods/projects
  193. mods/inhabitants
  194. mods/parliament
  195. mods/courts
  196. mods/opinions
  197. mods/spread
  198. mods/activity
  199. mods/stats
  200. mods/blockchain
  201. mods/shops
  202. mods/pixelia
  203. mods/pm
  204. mods/feed
  205. mods/tags
  206. mods/search
  207. mods/trending
  208. mods/agenda
  209. mods/cv
  210. mods/favorites
  211. mods/banking
  212. mods/ai
  213. mods/profile
  214. mods/peers
  215. mods/multiuser
  216. mods/larp
  217. mods/melody
  218. )
  219. DATE=$(date +%Y-%m-%d_%H-%M-%S)
  220. REPORT_DIR="test/results"
  221. mkdir -p "$REPORT_DIR"
  222. REPORT="$REPORT_DIR/unit_test_${DATE}.md"
  223. TMP=$(mktemp -d)
  224. trap "rm -rf $TMP" EXIT
  225. total_passed=0
  226. total_failed=0
  227. total_tests_passed=0
  228. total_tests_run=0
  229. failed_modules=()
  230. passing_modules=()
  231. module_outputs=()
  232. for m in "${MODULES[@]}"; do
  233. if [ ! -d "test/$m" ]; then
  234. echo "${YELLOW}skip $m (no tests yet)${RESET}"
  235. continue
  236. fi
  237. output=$(node test/run.js "$m" 2>&1)
  238. echo "$output"
  239. echo "$output" > "$TMP/$(echo $m | tr '/' '_').out"
  240. summary=$(echo "$output" | grep -E "passed" | tail -1)
  241. if [ -z "$summary" ]; then
  242. total_failed=$((total_failed + 1))
  243. failed_modules+=("$m")
  244. continue
  245. fi
  246. pcount=$(echo "$summary" | sed -E 's/.*\[32m([0-9]+)\/([0-9]+) passed.*/\1/' | grep -E "^[0-9]+$" || echo 0)
  247. tcount=$(echo "$summary" | sed -E 's/.*\[32m([0-9]+)\/([0-9]+) passed.*/\2/' | grep -E "^[0-9]+$")
  248. if [ -z "$tcount" ]; then
  249. pcount=$(echo "$summary" | sed -E 's/.*\[3[12]m([0-9]+)\/([0-9]+) passed.*/\1/')
  250. tcount=$(echo "$summary" | sed -E 's/.*\[3[12]m([0-9]+)\/([0-9]+) passed.*/\2/')
  251. fi
  252. total_tests_passed=$((total_tests_passed + ${pcount:-0}))
  253. total_tests_run=$((total_tests_run + ${tcount:-0}))
  254. if echo "$summary" | grep -q "failed"; then
  255. total_failed=$((total_failed + 1))
  256. failed_modules+=("$m")
  257. else
  258. total_passed=$((total_passed + 1))
  259. passing_modules+=("$m")
  260. fi
  261. done
  262. echo ""
  263. echo "${YELLOW}=== Aggregate ===${RESET}"
  264. echo "${GREEN}Modules passing: $total_passed${RESET}"
  265. if [ "$total_failed" -gt 0 ]; then
  266. echo "${RED}Modules with failures: $total_failed${RESET}"
  267. for f in "${failed_modules[@]}"; do echo " - $f"; done
  268. fi
  269. {
  270. echo "# Unit test report — $DATE"
  271. echo ""
  272. echo "**Tests passed:** $total_tests_passed / $total_tests_run"
  273. echo "**Modules passing:** $total_passed / ${#MODULES[@]}"
  274. if [ "$total_failed" -gt 0 ]; then
  275. echo "**Modules with failures:** $total_failed"
  276. fi
  277. echo ""
  278. echo "## ✅ Passing modules"
  279. echo ""
  280. for m in "${passing_modules[@]}"; do
  281. f="$TMP/$(echo $m | tr '/' '_').out"
  282. if [ -f "$f" ]; then
  283. summary=$(grep -E "passed in" "$f" | tail -1 | sed -E 's/\x1b\[[0-9;]*m//g')
  284. echo "- \`$m\` — $summary"
  285. grep -E "✓" "$f" | sed -E 's/\x1b\[[0-9;]*m//g' | sed 's/^ / - /'
  286. fi
  287. done
  288. if [ "$total_failed" -gt 0 ]; then
  289. echo ""
  290. echo "## ❌ Failing modules"
  291. echo ""
  292. for m in "${failed_modules[@]}"; do
  293. f="$TMP/$(echo $m | tr '/' '_').out"
  294. echo "### \`$m\`"
  295. echo ""
  296. if [ -f "$f" ]; then
  297. echo '```'
  298. cat "$f" | sed -E 's/\x1b\[[0-9;]*m//g'
  299. echo '```'
  300. else
  301. echo "_(no output captured)_"
  302. fi
  303. echo ""
  304. done
  305. fi
  306. echo ""
  307. echo "---"
  308. echo "_Generated by \`test/run.sh\` on $DATE._"
  309. } > "$REPORT"
  310. echo ""
  311. echo "${YELLOW}Report:${RESET} $REPORT"
  312. if [ "$SEED" = "1" ] && [ "$total_failed" -eq 0 ]; then
  313. echo ""
  314. echo "${YELLOW}=== Seeding dummy content into the test ~/.ssb ===${RESET}"
  315. node test/seed.js
  316. fi
  317. if [ "$total_failed" -gt 0 ]; then exit 1; fi
  318. exit 0