master ohmu/fastfetch-openbsd / tests / format.c
ohmu  ·  2026-10-15
  1#include "common/format.h"
  2#include "common/textModifier.h"
  3#include "fastfetch.h"
  4
  5#include <stdlib.h>
  6
  7static void verify(const char* format, const char* arg, const char* expected, int lineNo) {
  8    FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate();
  9    FF_STRBUF_AUTO_DESTROY formatter = ffStrbufCreateStatic(format);
 10    const FFformatarg arguments[] = { { .type = FF_ARG_TYPE_STRING, arg } };
 11    ffParseFormatString(&result, &formatter, 1, arguments);
 12    if (!ffStrbufEqualS(&result, expected)) {
 13        fprintf(stderr, FASTFETCH_TEXT_MODIFIER_ERROR "[%d] %s: expected \"%s\", got \"%s\"\n" FASTFETCH_TEXT_MODIFIER_RESET, lineNo, format, expected, result.chars);
 14        exit(1);
 15    }
 16}
 17
 18#define VERIFY(format, argument, expected) verify((format), (argument), (expected), __LINE__)
 19
 20int main(void) {
 21    instance.config.display.pipe = true;
 22
 23    {
 24        VERIFY("output({})", "12345 67890", "output(12345 67890)");
 25        VERIFY("output({1})", "12345 67890", "output(12345 67890)");
 26        VERIFY("output({})", "", "output()");
 27        VERIFY("output({1})", "", "output()");
 28    }
 29
 30    {
 31        VERIFY("output({1:20})", "12345 67890", "output(12345 67890)");
 32        VERIFY("output({1:11})", "12345 67890", "output(12345 67890)");
 33        VERIFY("output({1:-11})", "12345 67890", "output(12345 67890)");
 34        VERIFY("output({1:6})", "12345 67890", "output(12345)");
 35        VERIFY("output({:6})", "12345 67890", "output(12345)");
 36        VERIFY("output({:-6})", "12345 67890", "output(12345…)");
 37        VERIFY("output({:0})", "12345 67890", "output()");
 38        VERIFY("output({:})", "12345 67890", "output()");
 39    }
 40
 41    {
 42        VERIFY("output({1<20})", "12345 67890", "output(12345 67890         )");
 43        VERIFY("output({1<-20})", "12345 67890", "output(12345 67890         )");
 44        VERIFY("output({1<11})", "12345 67890", "output(12345 67890)");
 45        VERIFY("output({1<-11})", "12345 67890", "output(12345 67890)");
 46        VERIFY("output({1<6})", "12345 67890", "output(12345 )");
 47        VERIFY("output({<6})", "12345 67890", "output(12345 )");
 48        VERIFY("output({<-6})", "12345 67890", "output(12345…)");
 49        VERIFY("output({<0})", "12345 67890", "output()");
 50        VERIFY("output({<})", "12345 67890", "output()");
 51    }
 52
 53    {
 54        VERIFY("output({1>20})", "12345 67890", "output(         12345 67890)");
 55        VERIFY("output({1>-20})", "12345 67890", "output(         12345 67890)");
 56        VERIFY("output({1>11})", "12345 67890", "output(12345 67890)");
 57        VERIFY("output({1>-11})", "12345 67890", "output(12345 67890)");
 58        VERIFY("output({1>6})", "12345 67890", "output(12345 )");
 59        VERIFY("output({>6})", "12345 67890", "output(12345 )");
 60        VERIFY("output({>-6})", "12345 67890", "output(12345…)");
 61        VERIFY("output({>0})", "12345 67890", "output()");
 62        VERIFY("output({>})", "12345 67890", "output()");
 63    }
 64
 65    {
 66        VERIFY("output({1|20})", "12345 67890", "output(    12345 67890     )");
 67        VERIFY("output({1|-20})", "12345 67890", "output(    12345 67890     )");
 68        VERIFY("output({1|11})", "12345 67890", "output(12345 67890)");
 69        VERIFY("output({1|-11})", "12345 67890", "output(12345 67890)");
 70        VERIFY("output({1|6})", "12345 67890", "output(12345 )");
 71        VERIFY("output({|6})", "12345 67890", "output(12345 )");
 72        VERIFY("output({|-6})", "12345 67890", "output(12345…)");
 73        VERIFY("output({|0})", "12345 67890", "output()");
 74        VERIFY("output({|})", "12345 67890", "output()");
 75    }
 76
 77    {
 78        VERIFY("output({1n>20})", "12345 67890", "output({1n>20})");
 79        VERIFY("output({120})", "12345 67890", "output({120})");
 80        VERIFY("output({1:11})", "", "output()");
 81        VERIFY("output({2:2})", "", "output({2:2})");
 82    }
 83
 84    {
 85        VERIFY("output({1~0})", "12345 67890", "output(12345 67890)");
 86        VERIFY("output({1~1})", "12345 67890", "output(2345 67890)");
 87        VERIFY("output({1~10})", "12345 67890", "output(0)");
 88        VERIFY("output({1~20})", "12345 67890", "output()");
 89        VERIFY("output({1~-5})", "12345 67890", "output(67890)");
 90        VERIFY("output({1~-50})", "12345 67890", "output()");
 91        VERIFY("output({1~0,1})", "12345 67890", "output(1)");
 92        VERIFY("output({1~0,6})", "12345 67890", "output(12345 )");
 93        VERIFY("output({1~0,10})", "12345 67890", "output(12345 6789)");
 94        VERIFY("output({1~5,10})", "12345 67890", "output( 6789)");
 95        VERIFY("output({1~5,100})", "12345 67890", "output( 67890)");
 96        VERIFY("output({1~10,10})", "12345 67890", "output()");
 97        VERIFY("output({1~10,5})", "12345 67890", "output()");
 98        VERIFY("output({1~3,-3})", "12345 67890", "output(45 67)");
 99        VERIFY("output({1~-5,-3})", "12345 67890", "output(67)");
100        VERIFY("output({1~-0,10})", "12345 67890", "output(12345 6789)");
101        VERIFY("output({1~-3,-5})", "12345 67890", "output()");
102        VERIFY("output({1~})", "12345 67890", "output(12345 67890)");   // Same as {1~0}
103        VERIFY("output({1~-0})", "12345 67890", "output(12345 67890)"); // Same as {1~0}
104        VERIFY("output({1~,-1})", "12345 67890", "output(12345 6789)"); // Same as {1~0,-1}
105        VERIFY("output({1~,})", "12345 67890", "output()");             // Same as {1~0,0}
106    }
107
108    {
109        VERIFY("output({1n~0})", "12345 67890", "output({1n~0})");
110        VERIFY("output({1~<0})", "12345 67890", "output({1~<0})");
111        VERIFY("output({1~-})", "12345 67890", "output({1~-})");
112        VERIFY("output({1~-,1})", "12345 67890", "output({1~-,1})");
113        VERIFY("output({1~0,,1})", "12345 67890", "output({1~0,,1})");
114        VERIFY("output({1~0,1,})", "12345 67890", "output({1~0,1,})");
115        VERIFY("output({1~,0,1})", "12345 67890", "output({1~,0,1})");
116        VERIFY("output({2,0})", "12345 67890", "output({2,0})");
117    }
118
119    {
120        VERIFY("output({1:20}{1<20}{1>20})", "12345 67890", "output(12345 6789012345 67890                  12345 67890)");
121        VERIFY("output({?1}OK{?}{/1}NOT OK{/})", "12345 67890", "output(OK)");
122        VERIFY("output({?1}OK{?}{/1}NOT OK{/})", "", "output(NOT OK)");
123    }
124
125    {
126        VERIFY("output({1:3})", "\e[1m12345", "output(\e[1m123)");
127        VERIFY("output({1:-3})", "\e[1m12345", "output(\e[1m123…)");
128        VERIFY("output({1:3})", "\e[1m12345\e[m", "output(\e[1m123\e[m)");
129        VERIFY("output({1:-3})", "\e[1m12345\e[m", "output(\e[1m123…\e[m)");
130    }
131
132    {
133        VERIFY("output({1<8})", "\e[1m12345", "output(\e[1m12345   )");
134        VERIFY("output({1>8})", "\e[1m12345", "output(\e[1m   12345)");
135        VERIFY("output({1<8})", "\e[1m12345\e[m", "output(\e[1m12345   \e[m)");
136        VERIFY("output({1>8})", "\e[1m12345\e[m", "output(\e[1m   12345\e[m)");
137        VERIFY("output({1<1})", "\e[30;47m12345\e[m", "output(\e[30;47m1\e[m)");
138        VERIFY("output({1|8})", "\e[1m12345\e[m", "output(\e[1m 12345  \e[m)");
139        VERIFY("output({1|1})", "\e[30;47m12345\e[m", "output(\e[30;47m1\e[m)");
140    }
141
142    {
143        VERIFY("output({1~0})", "\e[1m12345", "output(\e[1m12345)");
144        VERIFY("output({1~1})", "\e[1m12345", "output(\e[1m2345)");
145        VERIFY("output({1~0})", "\e[1m12345\e[m", "output(\e[1m12345\e[m)");
146        VERIFY("output({1~1})", "\e[1m12345\e[m", "output(\e[1m2345\e[m)");
147        VERIFY("output({1~2})", "\e[30;47m12345\e[m", "output(\e[30;47m345\e[m)");
148    }
149
150    {
151        // All leading escape codes must be skipped, not just the first one
152        VERIFY("output({1:3})", "\e[31m\e[1m12345", "output(\e[31m\e[1m123)");
153        VERIFY("output({1:-3})", "\e[31m\e[1m12345", "output(\e[31m\e[1m123…)");
154        VERIFY("output({1<8})", "\e[31m\e[1m12345", "output(\e[31m\e[1m12345   )");
155        VERIFY("output({1~2})", "\e[31m\e[1m12345", "output(\e[31m\e[1m345)");
156
157        // ... and so must all trailing ones
158        VERIFY("output({1:3})", "\e[31m\e[1m12345\e[m\e[39m", "output(\e[31m\e[1m123\e[m\e[39m)");
159        VERIFY("output({1~2})", "\e[31m\e[1m12345\e[m\e[39m", "output(\e[31m\e[1m345\e[m\e[39m)");
160        VERIFY("output({1<8})", "\e[31m\e[1m12345\e[m\e[39m", "output(\e[31m\e[1m12345   \e[m\e[39m)");
161
162        // `\e[?25l` is a complete CSI sequence, not just `\e[?`
163        VERIFY("output({1:3})", "\e[?25l12345", "output(\e[?25l123)");
164        VERIFY("output({1~4})", "\e[?25l12345", "output(\e[?25l5)");
165    }
166
167#ifndef _WIN32 // Windows doesn't have setenv
168    {
169        ffListInit(&instance.config.display.constants);
170        ffStrbufInitStatic(FF_LIST_ADD(FFstrbuf, instance.config.display.constants), "CONST1");
171        ffStrbufInitStatic(FF_LIST_ADD(FFstrbuf, instance.config.display.constants), "CONST2");
172        setenv("FF_TEST", "ENVVAR", 1);
173        VERIFY("output({$FF_TEST})", "", "output(ENVVAR)");
174        VERIFY("output({$1})", "", "output(CONST1)");
175        VERIFY("output({$FF_TEST}{$1})", "", "output(ENVVARCONST1)");
176        VERIFY("output({$1}{$FF_TEST})", "", "output(CONST1ENVVAR)");
177        VERIFY("output({$FF_TEST}{$FF_TEST})", "", "output(ENVVARENVVAR)");
178        VERIFY("output({$1}{$-1})", "", "output(CONST1CONST2)");
179
180        VERIFY("output({$FF_INVAL})", "", "output({$FF_INVAL})");
181        VERIFY("output({$9}{$0}${-9})", "", "output({$9}{$0}${-9})");
182        VERIFY("output({$1NO})", "", "output({$1NO})");
183        ffListDestroy(&instance.config.display.constants);
184    }
185#endif
186
187    // Success
188    puts("\033[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET);
189}