From 065ee9e35e71b0b7c0c0c2a8842909830225d962 Mon Sep 17 00:00:00 2001 From: mfrasca Date: Tue, 2 Jun 2020 15:48:46 -0500 Subject: [PATCH] org-plot.el: adding unit tests this patch contains some minimal refactoring for the sake of unit-testing, and a couple of tests in the (new) file `testing/lisp/test-org-plot.el'. --- lisp/org-plot.el | 18 ++- testing/lisp/test-org-plot.el | 207 ++++++++++++++++++++++++++++++++++ 2 files changed, 220 insertions(+), 5 deletions(-) create mode 100644 testing/lisp/test-org-plot.el diff --git a/lisp/org-plot.el b/lisp/org-plot.el index a23195d2a..f4526db13 100644 --- a/lisp/org-plot.el +++ b/lisp/org-plot.el @@ -91,8 +91,8 @@ Return value is the point at the beginning of the table." (while (not (or (org-at-table-p) (< 0 (forward-line 1))))) (goto-char (org-table-begin))) -(defun org-plot/collect-options (&optional params) - "Collect options from an org-plot `#+Plot:' line. +(defun org-plot/collect-line-options (&optional params) + "Collect options from the org-plot `#+Plot:' line at point. Accepts an optional property list PARAMS, to which the options will be added. Returns the resulting property list." (interactive) @@ -101,6 +101,16 @@ will be added. Returns the resulting property list." (org-plot/add-options-to-plist params (match-string 1 line)) params))) +(defun org-plot/collect-table-options (&optional params) + "Collect options from the `#+Plot:' lines preceding the current table. +Point must immediately after last `#+Plot:' line. +Accepts an optional property list PARAMS, to which the options will be added. +Returns the accumulated property list." + (save-excursion (while (and (equal 0 (forward-line -1)) + (looking-at "[[:space:]]*#\\+")) + (setq params (org-plot/collect-line-options params)))) + params) + (defun org-plot-quote-timestamp-field (s) "Convert field S from timestamp to Unix time and export to gnuplot." (format-time-string org-plot-timestamp-fmt (org-time-string-to-time s))) @@ -299,9 +309,7 @@ line directly before or after the table." (plist-put params :labels (nth 0 table))) ; headers to labels (setf table (delq 'hline (cdr table)))) ; clean non-data from table ;; Collect options. - (save-excursion (while (and (equal 0 (forward-line -1)) - (looking-at "[[:space:]]*#\\+")) - (setf params (org-plot/collect-options params)))) + (setq params (org-plot/collect-table-options params)) ;; Dump table to datafile (very different for grid). (pcase (plist-get params :plot-type) (`2d (org-plot/gnuplot-to-data table data-file params)) diff --git a/testing/lisp/test-org-plot.el b/testing/lisp/test-org-plot.el new file mode 100644 index 000000000..b23075050 --- /dev/null +++ b/testing/lisp/test-org-plot.el @@ -0,0 +1,207 @@ +;;; test-org-plot.el --- Tests for Org Plot library -*- lexical-binding: t; -*- + +;; Copyright (C) 2020 Mario Frasca + +;; Author: Mario Frasca + +;; This file is not part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Code: + +(require 'org-test) +(require 'org-plot) + + +;; General auxiliaries + + +(ert-deftest test-org-plot/collect-line-options () + "Test `org-plot/collect-line-options' specifications." + ;; no options specified in table, no defaults + (should + (equal nil + (org-test-with-temp-text + "| 1 |" + (org-plot/collect-line-options)))) + ;; no options specified in table, keeps all defaults + (should + (equal '(:ind 1 :deps 2 3) + (org-test-with-temp-text + "| 1 |" + (org-plot/collect-line-options '(:ind 1 :deps 2 3))))) + ;; the independent column + (should + (equal '(:ind 1) + (org-test-with-temp-text + "#+PLOT: ind:1\n| 1 |" + (org-plot/collect-line-options)))) + ;; overruling default + (should + (equal '(:ind 2) + (org-test-with-temp-text + "#+PLOT: ind:2\n| 1 | 2 |" + (org-plot/collect-line-options '(:ind 1))))) + ;; appends to already collected + (should + (equal '(:deps (1 3) :ind 2 ) + (org-test-with-temp-text + "#+PLOT: ind:2\n| 1 | 2 | 3 |" + (org-plot/collect-line-options '(:deps (1 3)))))) + ;; appends to already collected + (should + (equal '(:ind 2 :deps (1 3) ) + (org-test-with-temp-text + "#+PLOT: ind:2\n| 1 | 2 | 3 |" + (org-plot/collect-line-options '(:ind 1 :deps (1 3)))))) + ;; multiple options from single line + (should ; `op' in add-options-to-plist defines order of options + (equal '(:plot-type 2d :title "example table" :ind 1 :deps (2 3) :with (lines points)) + (org-test-with-temp-text + "#+PLOT: title:\"example table\" ind:1 deps:(2 3) type:2d with:(lines points)" + (org-plot/collect-line-options)))) + ;; with, as a single string + (should + (equal '(:with lines) + (org-test-with-temp-text + "#+PLOT: with:lines\n| 1 | 2 | 3 |" + (org-plot/collect-line-options)))) + ;; with, as a list + (should + (equal '(:with (lines hist)) + (org-test-with-temp-text + "#+PLOT: with:(lines hist)\n| 1 | 2 | 3 |" + (org-plot/collect-line-options))))) + + +(ert-deftest test-org-plot/collect-table-options () + "Test `org-plot/collect-table-options' specifications." + ;; all options on a single lines + (should ; `op' in add-options-to-plist defines order of options + (equal '(:plot-type 2d :title "example table" :ind 1 :deps (2 3) :with (lines points)) + (org-test-with-temp-text + "#+PLOT: title:\"example table\" ind:1 deps:(2 3) type:2d with:(lines points)\n" + (goto-char (point-max)) ; point must be on line after last options line + (org-plot/collect-table-options)))) + ;; multiple options from multiple lines + (should ; `op' in add-options-to-plist defines order of options + (equal '(:plot-type 2d :with (lines points) :title "example table" :ind 1 :deps (2 3)) + (org-test-with-temp-text + "#+PLOT: title:\"example table\" ind:1 deps:(2 3)\n#+PLOT: type:2d with:(lines points)\n" + (goto-char (point-max)) ; point must be on line after last options line + (org-plot/collect-table-options)))) + ;; one option per line, several lines (collected going up) + (should + (equal '(:with (lines points) :plot-type 2d :deps (2 3) :ind 1 :title "example table") + (org-test-with-temp-text + "#+PLOT: title:\"example table\"\n#+PLOT: ind:1\n#+PLOT: deps:(2 3)\n#+PLOT: type:2d\n#+PLOT: with:(lines points)\n" + (goto-char (point-max)) ; point must be on line after last options line + (org-plot/collect-table-options))))) + + +(ert-deftest test-org-plot/goto-nearest-table () + "Test `org-plot/goto-nearest-table' specifications." + ;; at table beginning stays put + (should + (= 1 + (org-test-with-temp-text + "| 1 | 2 | 3 |\n| 1 | 2 | 3 |\n| 1 | 2 | 3 |" + (org-plot/goto-nearest-table)))) + ;; anywhere within the table moves back to table beginning + (should + (= 1 + (org-test-with-temp-text + "| 1 | 2 | 3 |\n| 1 | 2 | 3 |\n| 1 | 2 | 3 |" + (goto-char 4) + (org-plot/goto-nearest-table)))) + ;; on newline at end of table, goes back to table beginning + (should + (= 1 + (org-test-with-temp-text + "| 1 | 2 | 3 |\n| 1 | 2 | 3 |\n| 1 | 2 | 3 |\n" + (goto-char (point-max)) + (org-plot/goto-nearest-table)))) + ;; farther away than newline at end of last table, moves to end of buffer + (should + (= 44 + (org-test-with-temp-text + "| 1 | 2 | 3 |\n| 1 | 2 | 3 |\n| 1 | 2 | 3 |\n\n" + (goto-char (point-max)) + (org-plot/goto-nearest-table)))) + ;; moves to beginning of data, not metadata + (should + (= 26 + (org-test-with-temp-text + "#+PLOT: ind:1 deps:(2 3)\n| 1 | 2 | 3 |\n| 1 | 2 | 3 |\n| 1 | 2 | 3 |" + (org-plot/goto-nearest-table)))) + ;; in case there's two tables + (should + (= 30 + (org-test-with-temp-text + "| 1 | 2 | 3 |\n| 1 | 2 | 3 |\n\n| 1 | 2 | 3 |" + (goto-char (point-max)) + (org-plot/goto-nearest-table))))) + + +(ert-deftest test-org-plot/gnuplot-script () + "Regression Test for `org-plot/gnuplot-script'." + (should + (equal "reset +set datafile separator \"\\t\" +plot FILENAME using 1:2 with points title '2',\\ + FILENAME using 1:3 with points title '3'" + (org-test-with-temp-text + "| 1 | 2 | 3 |\n| 1 | 2 | 3 |\n| 1 | 2 | 3 |" + (let ((data-file (make-temp-file "org-plot")) + (table (org-table-to-lisp)) + (params '(:ind 1 :deps (2 3) :plot-type 2d :with points))) + (org-plot/gnuplot-to-data table data-file params) + (org-plot/gnuplot-script data-file 3 params t) + (replace-regexp-in-string (concat "'" (regexp-quote data-file) "'") + "FILENAME" + (org-plot/gnuplot-script data-file 3 params) + nil 'LITERAL))))) + (should + (equal "reset +set title 'example table' +set datafile separator \"\\t\" +plot FILENAME using 1:2 with lines title 'ylab',\\ + FILENAME using 1:3 with lines title 'zlab'" + (org-test-with-temp-text + "\ +#+PLOT: title:\"example table\" ind:1 deps:(2 3) type:2d with:lines +#+PLOT: labels:(\"xlab\" \"ylab\" \"zlab\") +#+TBLNAME:org-plot-example-1 +| x | y | z | +|-----+------+------| +| 0.1 | 0.42 | 0.37 | +| 0.2 | 0.31 | 0.33 | +| 0.3 | 0.24 | 0.28 | +| 0.4 | 0.27 | 0.23 | +" + (org-plot/goto-nearest-table) + (let ((data-file (make-temp-file "org-plot")) + (table (org-table-to-lisp)) + params) + (setq params (org-plot/collect-table-options params)) + (org-plot/gnuplot-to-data table data-file params) + (org-plot/gnuplot-script data-file 3 params t) + (replace-regexp-in-string (concat "'" (regexp-quote data-file) "'") + "FILENAME" + (org-plot/gnuplot-script data-file 3 params) + nil 'LITERAL)))))) + +(provide 'test-org-plot) +;;; test-org-plot.el end here -- 2.20.1