├── .all-contributorsrc
├── .devcontainer
├── Dockerfile
└── devcontainer.json
├── .git-hooks
├── commit-msg
└── pre-commit
├── .gitattributes
├── .github
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── FUNDING.yml
├── PULL_REQUEST_TEMPLATE.md
├── SECURITY.md
├── dependabot.yml
├── vpn
│ └── config.ovpn
└── workflows
│ ├── main.yml
│ ├── notmain.yml
│ └── run-tests.yml
├── .gitignore
├── .gitpod.dockerfile
├── .gitpod.yml
├── .npmignore
├── .sasjslint
├── .vscode
├── .editorconfig
├── extensions.json
└── settings.json
├── LICENSE
├── README.md
├── all.sas
├── base
├── mf_abort.sas
├── mf_dedup.sas
├── mf_deletefile.sas
├── mf_existds.sas
├── mf_existfeature.sas
├── mf_existfileref.sas
├── mf_existfunction.sas
├── mf_existvar.sas
├── mf_existvarlist.sas
├── mf_fmtdttm.sas
├── mf_getapploc.sas
├── mf_getattrc.sas
├── mf_getattrn.sas
├── mf_getengine.sas
├── mf_getfilesize.sas
├── mf_getfmtlist.sas
├── mf_getfmtname.sas
├── mf_getgitbranch.sas
├── mf_getkeyvalue.sas
├── mf_getplatform.sas
├── mf_getquotedstr.sas
├── mf_getschema.sas
├── mf_getuniquefileref.sas
├── mf_getuniquelibref.sas
├── mf_getuniquename.sas
├── mf_getuser.sas
├── mf_getvalue.sas
├── mf_getvarcount.sas
├── mf_getvarformat.sas
├── mf_getvarlen.sas
├── mf_getvarlist.sas
├── mf_getvarnum.sas
├── mf_getvartype.sas
├── mf_getxengine.sas
├── mf_increment.sas
├── mf_isblank.sas
├── mf_isdir.sas
├── mf_isint.sas
├── mf_islibds.sas
├── mf_loc.sas
├── mf_mimetype.sas
├── mf_mkdir.sas
├── mf_mval.sas
├── mf_nobs.sas
├── mf_readfile.sas
├── mf_trimstr.sas
├── mf_uid.sas
├── mf_verifymacvars.sas
├── mf_wordsinstr1andstr2.sas
├── mf_wordsinstr1butnotstr2.sas
├── mf_writefile.sas
├── mp_abort.sas
├── mp_aligndecimal.sas
├── mp_appendfile.sas
├── mp_applyformats.sas
├── mp_assert.sas
├── mp_assertcols.sas
├── mp_assertcolvals.sas
├── mp_assertdsobs.sas
├── mp_assertscope.sas
├── mp_base64copy.sas
├── mp_binarycopy.sas
├── mp_chop.sas
├── mp_cleancsv.sas
├── mp_cntlout.sas
├── mp_copyfolder.sas
├── mp_coretable.sas
├── mp_createconstraints.sas
├── mp_createwebservice.sas
├── mp_csv2ds.sas
├── mp_deleteconstraints.sas
├── mp_deletefolder.sas
├── mp_dictionary.sas
├── mp_dirlist.sas
├── mp_distinctfmtvalues.sas
├── mp_dropmembers.sas
├── mp_ds2cards.sas
├── mp_ds2csv.sas
├── mp_ds2ddl.sas
├── mp_ds2fmtds.sas
├── mp_ds2inserts.sas
├── mp_ds2md.sas
├── mp_ds2squeeze.sas
├── mp_dsmeta.sas
├── mp_filtercheck.sas
├── mp_filtergenerate.sas
├── mp_filterstore.sas
├── mp_filtervalidate.sas
├── mp_getcols.sas
├── mp_getconstraints.sas
├── mp_getdbml.sas
├── mp_getddl.sas
├── mp_getformats.sas
├── mp_getmaxvarlengths.sas
├── mp_getpk.sas
├── mp_gitadd.sas
├── mp_gitlog.sas
├── mp_gitreleaseinfo.sas
├── mp_gitstatus.sas
├── mp_gsubfile.sas
├── mp_guesspk.sas
├── mp_hashdataset.sas
├── mp_hashdirectory.sas
├── mp_include.sas
├── mp_init.sas
├── mp_jsonout.sas
├── mp_lib2cards.sas
├── mp_lib2inserts.sas
├── mp_loadformat.sas
├── mp_lockanytable.sas
├── mp_lockfilecheck.sas
├── mp_makedata.sas
├── mp_md5.sas
├── mp_perflog.sas
├── mp_prevobs.sas
├── mp_recursivejoin.sas
├── mp_replace.sas
├── mp_reseterror.sas
├── mp_resetoption.sas
├── mp_retainedkey.sas
├── mp_runddl.sas
├── mp_searchcols.sas
├── mp_searchdata.sas
├── mp_setkeyvalue.sas
├── mp_sortinplace.sas
├── mp_stackdiffs.sas
├── mp_storediffs.sas
├── mp_stprequests.sas
├── mp_streamfile.sas
├── mp_stripdiffs.sas
├── mp_testjob.sas
├── mp_testservice.sas
├── mp_testwritespeedlibrary.sas
├── mp_tree.sas
├── mp_unzip.sas
├── mp_updatevarlength.sas
├── mp_validatecol.sas
├── mp_wait4file.sas
├── mp_webin.sas
└── mp_zip.sas
├── build.py
├── ddl
├── mddl_dc_difftable.sas
├── mddl_dc_filterdetail.sas
├── mddl_dc_filtersummary.sas
├── mddl_dc_locktable.sas
├── mddl_dc_maxkeytable.sas
└── mddl_sas_cntlout.sas
├── fcmp
├── mcf_getfmttype.sas
├── mcf_init.sas
├── mcf_length.sas
└── mcf_string2file.sas
├── lua
├── gsubfile.lua
├── json.lua
├── ml_gsubfile.sas
└── ml_json.sas
├── main.dox
├── meta
├── mm_adduser2group.sas
├── mm_assigndirectlib.sas
├── mm_assignlib.sas
├── mm_createapplication.sas
├── mm_createdataset.sas
├── mm_createdocument.sas
├── mm_createfolder.sas
├── mm_createlibrary.sas
├── mm_createstp.sas
├── mm_createwebservice.sas
├── mm_deletedocument.sas
├── mm_deletelibrary.sas
├── mm_deletestp.sas
├── mm_getauthinfo.sas
├── mm_getcols.sas
├── mm_getdetails.sas
├── mm_getdirectories.sas
├── mm_getdocument.sas
├── mm_getfoldermembers.sas
├── mm_getfoldertree.sas
├── mm_getgroupmembers.sas
├── mm_getgroups.sas
├── mm_getlibmetadiffs.sas
├── mm_getlibs.sas
├── mm_getobjects.sas
├── mm_getpublictypes.sas
├── mm_getrepos.sas
├── mm_getroles.sas
├── mm_getservercontexts.sas
├── mm_getstpcode.sas
├── mm_getstpinfo.sas
├── mm_getstps.sas
├── mm_gettableid.sas
├── mm_gettables.sas
├── mm_gettree.sas
├── mm_gettypes.sas
├── mm_getusers.sas
├── mm_getwebappsrvprops.sas
├── mm_spkexport.sas
├── mm_tree.sas
├── mm_updateappextension.sas
├── mm_updatedocument.sas
├── mm_updatestpservertype.sas
├── mm_updatestpsourcecode.sas
└── mm_webout.sas
├── metax
├── mmx_createmetafolder.sas
├── mmx_deletemetafolder.sas
└── mmx_spkexport.sas
├── package-lock.json
├── package.json
├── sasjs
├── doxy
│ ├── Doxyfile
│ ├── DoxygenLayout.xml
│ ├── Macro_core_website_1.png
│ ├── doxygen.svg
│ ├── favicon.ico
│ ├── logo.png
│ ├── new_footer.html
│ ├── new_header.html
│ ├── new_stylesheet.css
│ └── runningman.jpg
├── sasjsconfig.json
└── utils
│ ├── build.sh
│ └── create_sas_package.sas
├── server
├── mfs_httpheader.sas
├── ms_adduser2group.sas
├── ms_createfile.sas
├── ms_creategroup.sas
├── ms_createuser.sas
├── ms_createwebservice.sas
├── ms_deletefile.sas
├── ms_getfile.sas
├── ms_getgroups.sas
├── ms_getusers.sas
├── ms_runstp.sas
├── ms_testservice.sas
├── ms_triggerstp.sas
└── ms_webout.sas
├── tests
├── base
│ ├── mcf_getfmttype.test.sas
│ ├── mcf_init.test.sas
│ ├── mcf_length.test.sas
│ ├── mcf_string2file.test.sas
│ ├── mf_dedup.test.sas
│ ├── mf_deletefile.test.sas
│ ├── mf_existds.test.sas
│ ├── mf_existfileref.test.sas
│ ├── mf_existfunction.test.sas
│ ├── mf_existvar.test.sas
│ ├── mf_fmtdttm.test.sas
│ ├── mf_getapploc.test.sas
│ ├── mf_getfilesize.test.sas
│ ├── mf_getfmtlist.test.sas
│ ├── mf_getfmtname.test.sas
│ ├── mf_getgitbranch.test.sas
│ ├── mf_getuniquefileref.test.sas
│ ├── mf_getuniquelibref.test.sas
│ ├── mf_getvarcount.test.sas
│ ├── mf_getvarlist.test.sas
│ ├── mf_increment.test.sas
│ ├── mf_isint.test.sas
│ ├── mf_islibds.test.sas
│ ├── mf_mimetype.test.sas
│ ├── mf_readfile.test.sas
│ ├── mf_verifymacvars.test.sas
│ ├── mf_wordsinstr1andstr2.test.sas
│ ├── mf_wordsinstr1butnotstr2.test.sas
│ ├── mf_writefile.test.sas
│ ├── mp_abort.test.nofix.sas
│ ├── mp_aligndecimal.test.sas
│ ├── mp_appendfile.test.sas
│ ├── mp_applyformats.test.sas
│ ├── mp_assert.test.sas
│ ├── mp_assertcolvals.test.sas
│ ├── mp_assertdsobs.test.sas
│ ├── mp_assertscope.test.sas
│ ├── mp_base64copy.test.sas
│ ├── mp_binarycopy.test.sas
│ ├── mp_chop.test.sas
│ ├── mp_cleancsv.test.sas
│ ├── mp_cntlout.test.sas
│ ├── mp_copyfolder.test.sas
│ ├── mp_coretable.test.sas
│ ├── mp_createwebservice.test.sas
│ ├── mp_deletefolder.test.sas
│ ├── mp_dictionary.test.sas
│ ├── mp_dirlist.test.sas
│ ├── mp_ds2cards.test.sas
│ ├── mp_ds2csv.test.1.sas
│ ├── mp_ds2csv.test.2.sas
│ ├── mp_ds2fmtds.test.sas
│ ├── mp_ds2inserts.test.sas
│ ├── mp_ds2md.test.sas
│ ├── mp_ds2squeeze.test.sas
│ ├── mp_dsmeta.test.sas
│ ├── mp_filtercheck.test.sas
│ ├── mp_filtergenerate.test.sas
│ ├── mp_filterstore.test.1.sas
│ ├── mp_filterstore.test.2.sas
│ ├── mp_filtervalidate.test.sas
│ ├── mp_getcols.test.sas
│ ├── mp_getconstraints.test.sas
│ ├── mp_getddl.test.sas
│ ├── mp_getformats.test.sas
│ ├── mp_getmaxvarlengths.test.sas
│ ├── mp_getpk.test.sas
│ ├── mp_gitadd.test.sas
│ ├── mp_gitlog.test.sas
│ ├── mp_gitreleaseinfo.test.sas
│ ├── mp_gitstatus.test.sas
│ ├── mp_gsubfile.test.sas
│ ├── mp_hashdataset.test.sas
│ ├── mp_hashdirectory.test.sas
│ ├── mp_init.test.sas
│ ├── mp_jsonout.test.1.sas
│ ├── mp_jsonout.test.2.sas
│ ├── mp_jsonout.test.3.sas
│ ├── mp_lib2inserts.test.sas
│ ├── mp_loadformat.test.1.sas
│ ├── mp_loadformat.test.2.sas
│ ├── mp_lockanytable.test.sas
│ ├── mp_lockfilecheck.test.sas
│ ├── mp_makedata.test.sas
│ ├── mp_md5.test.sas
│ ├── mp_replace.test.sas
│ ├── mp_reseterror.test.sas
│ ├── mp_resetoption.test.sas
│ ├── mp_retainedkey.test.sas
│ ├── mp_searchcols.test.sas
│ ├── mp_searchdata.test.sas
│ ├── mp_sortinplace.test.sas
│ ├── mp_stackdiffs.test.sas
│ ├── mp_storediffs.test.sas
│ ├── mp_streamfile.test.sas
│ ├── mp_stripdiffs.test.sas
│ ├── mp_validatecol.test.sas
│ ├── mp_webin.test.sas
│ └── mp_zip.test.sas
├── ddlonly
│ ├── mddl_dc_difftable.test.sas
│ ├── mddl_dc_filterdetail.test.sas
│ ├── mddl_dc_filtersummary.test.sas
│ ├── mddl_dc_locktable.test.sas
│ ├── mddl_dc_maxkeytable.test.sas
│ └── mddl_sas_cntlout.test.sas
├── sas9only
│ ├── mm_getauthinfo.test.sas
│ ├── mm_spkexport.test.sas
│ └── mm_webout.test.sas
├── serveronly
│ ├── mfs_httpheader.test.sas
│ ├── ms_adduser2group.test.sas
│ ├── ms_createfile.test.sas
│ ├── ms_creategroup.test.sas
│ ├── ms_createuser.test.sas
│ ├── ms_createwebservice.test.sas
│ ├── ms_deletefile.test.sas
│ ├── ms_getfile.test.sas
│ ├── ms_getgroups.test.sas
│ ├── ms_getusers.test.sas
│ ├── ms_runstp.test.sas
│ ├── ms_testservice.test.sas
│ ├── ms_triggerstp.test.sas
│ └── ms_webout.test.sas
├── testinit.sas
├── testterm.sas
├── viyaonly
│ ├── mfv_existfile.test.sas
│ ├── mfv_existfolder.test.sas
│ ├── mfv_getfolderpath.test.sas
│ ├── mfv_getpathuri.test.sas
│ ├── mv_createfile.test.sas
│ ├── mv_createfolder.test.sas
│ ├── mv_createwebservice.test.sas
│ ├── mv_deleteviyafolder.test.sas
│ ├── mv_getfoldermembers.test.sas
│ ├── mv_getjobcode.test.sas
│ ├── mv_getjoblog.test.sas
│ ├── mv_getjobresult.test.sas
│ ├── mv_jobflow.test.1.sas
│ ├── mv_jobflow.test.2.sas
│ ├── mv_registerclient.test.1.sas
│ ├── mv_registerclient.test.2.sas
│ └── mv_webout.test.sas
└── x-platform
│ ├── mx_getcode.test.sas
│ ├── mx_getgroups.test.sas
│ └── mx_testservice.test.sas
├── viya
├── mfv_existfile.sas
├── mfv_existfolder.sas
├── mfv_existsashdat.sas
├── mfv_getfolderpath.sas
├── mfv_getpathuri.sas
├── mv_createfile.sas
├── mv_createfolder.sas
├── mv_createjob.sas
├── mv_createwebservice.sas
├── mv_deletefoldermember.sas
├── mv_deletejes.sas
├── mv_deleteviyafolder.sas
├── mv_getclients.sas
├── mv_getfoldermembers.sas
├── mv_getgroupmembers.sas
├── mv_getgroups.sas
├── mv_getjobcode.sas
├── mv_getjoblog.sas
├── mv_getjobresult.sas
├── mv_getjobstate.sas
├── mv_getusergroups.sas
├── mv_getusers.sas
├── mv_jobexecute.sas
├── mv_jobflow.sas
├── mv_jobwaitfor.sas
├── mv_registerclient.sas
├── mv_tokenauth.sas
├── mv_tokenrefresh.sas
└── mv_webout.sas
└── xplatform
├── mx_createwebservice.sas
├── mx_getcode.sas
├── mx_getgroups.sas
└── mx_testservice.sas
/.devcontainer/Dockerfile:
--------------------------------------------------------------------------------
1 | # See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.233.0/containers/javascript-node/.devcontainer/base.Dockerfile
2 |
3 | # [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster
4 | ARG VARIANT="18-bullseye"
5 | FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT}
6 |
7 | RUN apt-get update \
8 | && apt-get install -y doxygen
9 |
--------------------------------------------------------------------------------
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
2 | // https://github.com/microsoft/vscode-dev-containers/tree/v0.233.0/containers/typescript-node
3 | {
4 | "name": "Node.js & TypeScript",
5 | "build": {
6 | "dockerfile": "Dockerfile",
7 | // Update 'VARIANT' to pick a Node version: 18, 16, 14.
8 | // Append -bullseye or -buster to pin to an OS version.
9 | // Use -bullseye variants on local on arm64/Apple Silicon.
10 | "args": {
11 | "VARIANT": "16-bullseye"
12 | }
13 | },
14 | // Set *default* container specific settings.json values on container create.
15 | "settings": {},
16 | // Add the IDs of extensions you want installed when the container is created.
17 | "extensions": [
18 | "SASjs.sasjs-for-vscode"
19 | ],
20 | // Use 'forwardPorts' to make a list of ports inside the container available locally.
21 | // "forwardPorts": [],
22 | // Use 'postCreateCommand' to run commands after the container is created.
23 | "postCreateCommand": "npm i && npm i -g @sasjs/cli",
24 | // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
25 | "remoteUser": "node"
26 | }
--------------------------------------------------------------------------------
/.git-hooks/commit-msg:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | RED="\033[1;31m"
3 | GREEN="\033[1;32m"
4 |
5 | # Get the commit message (the parameter we're given is just the path to the
6 | # temporary file which holds the message).
7 | commit_message=$(cat "$1")
8 |
9 | if (echo "$commit_message" | grep -Eq "^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\([a-z \-]+\))?!?: .+$") then
10 | echo "${GREEN} ✔ Commit message meets Conventional Commit standards"
11 | exit 0
12 | fi
13 |
14 | echo "${RED}❌ Commit message does not meet the Conventional Commit standard!"
15 | echo "An example of a valid message is:"
16 | echo " feat(login): add the 'remember me' button"
17 | echo "ℹ More details at: https://www.conventionalcommits.org/en/v1.0.0/#summary"
18 | exit 1
--------------------------------------------------------------------------------
/.git-hooks/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Ensure lint is passing
4 | LINT=`sasjs lint`
5 | if [[ "$LINT" != *"All matched files use @sasjs/lint code style!" ]]; then
6 | echo "$LINT"
7 | echo "To commit in spite of these warnings, use the -n parameter."
8 | exit 1
9 | fi
10 |
11 | # Avoid commits to the master branch
12 | BRANCH=`git rev-parse --abbrev-ref HEAD`
13 |
14 | if [[ "$BRANCH" =~ ^(master|main|develop)$ ]]; then
15 | echo "You are on branch $BRANCH. Are you sure you want to commit to this branch?"
16 | echo "If so, commit with -n to bypass the pre-commit hook."
17 | exit 1
18 | fi
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto eol=lf
2 |
--------------------------------------------------------------------------------
/.github/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG
2 |
3 | As the changes are managed automatically in github, we don't generate an additional changelog. To view the fixes/features in each release, check out the releases page below:
4 |
5 | [https://github.com/sasjs/core/releases](https://github.com/sasjs/core/releases)
6 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | custom: https://getalby.com/p/sasjs
4 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Issue
2 |
3 | Link any related issue(s) in this section.
4 |
5 | ## Intent
6 |
7 | What this PR intends to achieve.
8 |
9 | ## Implementation
10 |
11 | What code changes have been made to achieve the intent.
12 |
13 | ## Checks
14 |
15 | - [ ] Code is formatted correctly (`sasjs lint`).
16 | - [ ] Any new functionality has been unit tested.
17 | - [ ] All unit tests are passing (`sasjs test`).
18 | - [ ] The PR desc or underlying commits follow the [Conventional Commit](https://www.conventionalcommits.org) standard
19 |
--------------------------------------------------------------------------------
/.github/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | Security is an extremely high priority when it comes to the SASjs product suite. We take a number of steps across all repositories to minimise risk, such as:
4 |
5 | * Regular dependabot updates
6 | * Snyk reports
7 | * Minimising dependencies, especially production dependencies (sasjs/core has NONE)
8 | * Testing & Code review process
9 |
10 | ## Supported Versions
11 |
12 | We support only the latest version
13 |
14 | ## Reporting a Vulnerability
15 |
16 | We welcome disclosures of all kinds in relation to all the SASjs libraries. You can submit them here: [https://sasapps.io/contact-us](https://sasapps.io/contact-us)
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: npm
4 | directory: '/'
5 | schedule:
6 | interval: monthly
7 | open-pull-requests-limit: 3
8 | allow:
9 | - dependency-type: "production"
10 |
--------------------------------------------------------------------------------
/.github/vpn/config.ovpn:
--------------------------------------------------------------------------------
1 | # Client
2 | client
3 | tls-client
4 | dev tun
5 | # this will connect with whatever proto DNS tells us (https://community.openvpn.net/openvpn/ticket/934)
6 | proto udp
7 | remote vpn.4gl.io 7194
8 | resolv-retry infinite
9 | # this will fallback from udp6 to udp4 as well
10 | connect-timeout 5
11 | data-ciphers AES-256-CBC:AES-256-GCM
12 | auth SHA256
13 | script-security 2
14 | keepalive 10 120
15 | remote-cert-tls server
16 |
17 | # Keys
18 | ca ca.crt
19 | cert user.crt
20 | key user.key
21 | tls-auth tls.key 1
22 |
23 | # Security
24 | nobind
25 | persist-key
26 | persist-tun
27 | verb 3
28 |
--------------------------------------------------------------------------------
/.github/workflows/notmain.yml:
--------------------------------------------------------------------------------
1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages
3 |
4 | name: SASjs Core - Update all.sas
5 |
6 | on:
7 | push:
8 | branches-ignore:
9 | - main
10 |
11 | jobs:
12 | release:
13 | runs-on: ubuntu-latest
14 | steps:
15 | - name: Checkout
16 | uses: actions/checkout@v4
17 |
18 | - name: Install dependencies
19 | run: |
20 | npm ci
21 | npm i -g @sasjs/cli@latest
22 |
23 | - name: Ensure all.sas is always up to date
24 | run: |
25 | git config user.name github-actions
26 | git config user.email github-actions@github.com
27 | python3 build.py
28 | git add all.sas
29 | git commit -m "chore: updating all.sas" --allow-empty
30 | git push
31 |
32 |
33 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | sasjsbuild/
4 | sasjsresults/
5 |
6 | # avoid filenames with spaces being committed to source control
7 | **\ **
8 |
9 | # ignore the mc_* files - containing macros for individual libraries
10 | mc_*
11 |
12 | # ignore .env files as they can contain sasjs access tokens
13 | *.env*
14 |
15 | ~
16 |
17 |
--------------------------------------------------------------------------------
/.gitpod.dockerfile:
--------------------------------------------------------------------------------
1 | FROM gitpod/workspace-full
2 |
3 | RUN sudo apt-get update \
4 | && sudo apt-get install -y doxygen \
5 | && sudo apt-get install -y graphviz \
6 | && sudo rm -rf /var/lib/apt/lists/*
7 |
--------------------------------------------------------------------------------
/.gitpod.yml:
--------------------------------------------------------------------------------
1 | tasks:
2 | - init: npm install -g npm
3 | - command: npm i
4 | - command: npm i -g @sasjs/cli
5 |
6 | image:
7 | file: .gitpod.dockerfile
8 | vscode:
9 | extensions:
10 | - sasjs.sasjs-for-vscode
11 |
12 | github:
13 | prebuilds:
14 | # enable for the master/default branch (defaults to true)
15 | master: true
16 | # enable for all branches in this repo (defaults to false)
17 | branches: false
18 | # enable for pull requests coming from this repo (defaults to true)
19 | pullRequests: true
20 | # enable for pull requests coming from forks (defaults to false)
21 | pullRequestsFromForks: true
22 | # add a "Review in Gitpod" button as a comment to pull requests (defaults to true)
23 | addComment: true
24 | # add a "Review in Gitpod" button to pull requests (defaults to false)
25 | addBadge: false
26 | # add a label once the prebuild is ready to pull requests (defaults to false)
27 | addLabel: prebuilt-in-gitpod
28 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | all.sas
2 | build.py
3 | .gitpod*
4 | tests/
5 | sasjs/
6 | .github/
7 | .git-hooks/
8 | .vscode/
9 | make_singlefile.sh
10 | *.md
11 | .all-contributorsrc
12 |
--------------------------------------------------------------------------------
/.sasjslint:
--------------------------------------------------------------------------------
1 | {
2 | "noTrailingSpaces": true,
3 | "noEncodedPasswords": true,
4 | "hasDoxygenHeader": true,
5 | "hasMacroNameInMend": true,
6 | "hasMacroParentheses": true,
7 | "lineEndings": "lf",
8 | "noGremlins": true,
9 | "noNestedMacros": false,
10 | "noSpacesInFileNames": true,
11 | "maxLineLength": 300,
12 | "lowerCaseFileNames": true,
13 | "noTabs": true,
14 | "indentationMultiple": 2
15 | }
16 |
--------------------------------------------------------------------------------
/.vscode/.editorconfig:
--------------------------------------------------------------------------------
1 | {
2 | "search.exclude": {
3 | "**/sasjsbuild/**": true,
4 | "**/dist/**":true
5 | },
6 | "editor.insertSpaces": true,
7 | "editor.tabSize": 2,
8 | "trim_trailing_whitespace": true
9 | }
10 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "sasjs.sasjs-for-vscode"
4 | ]
5 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.tabSize": 2,
3 | "editor.insertSpaces": true,
4 | "editor.detectIndentation": true,
5 | "editor.formatOnSave": true,
6 | "editor.rulers": [
7 | 80
8 | ],
9 | "files.trimTrailingWhitespace": true,
10 | "sasjs-for-vscode.target": "docsonly",
11 | "sasjs-for-vscode.isLocal": true
12 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2021 (Allan Bowe)
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/base/mf_abort.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Abort, ungracefully
4 | @details Will abort with a straightforward %abort if the condition is true.
5 |
6 | @param [in] mac= (mf_abort.sas) Name of calling macro (is printed to the log)
7 | @param [in] msg= ( ) Additional string to print to the log
8 | @param [in] iftrue= (%str(1=1)) Conditional logic under which to perform the
9 | abort
10 |
11 |
Related Macros
12 | @li mp_abort.sas
13 |
14 | @version 9.2
15 | @author Allan Bowe
16 | @cond
17 | **/
18 |
19 | %macro mf_abort(mac=mf_abort.sas, msg=, iftrue=%str(1=1)
20 | )/des='ungraceful abort' /*STORE SOURCE*/;
21 |
22 | %if not(%eval(%unquote(&iftrue))) %then %return;
23 |
24 | %put NOTE: /// mf_abort macro executing //;
25 | %if %length(&mac)>0 %then %put NOTE- called by &mac;
26 | %put NOTE - &msg;
27 |
28 | %abort;
29 |
30 | %mend mf_abort;
31 |
32 | /** @endcond */
33 |
--------------------------------------------------------------------------------
/base/mf_dedup.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief de-duplicates a macro string
4 | @details Removes all duplicates from a string of words. A delimeter can be
5 | chosen. Is inspired heavily by this excellent [macro](
6 | https://github.com/scottbass/SAS/blob/master/Macro/dedup_mstring.sas) from
7 | [Scott Base](https://www.linkedin.com/in/scottbass). Case sensitive.
8 |
9 | Usage:
10 |
11 | %let str=One two one two and through and through;
12 | %put %mf_dedup(&str);
13 | %put %mf_dedup(&str,outdlm=%str(,));
14 |
15 | Which returns:
16 |
17 | > One two one and through
18 | > One,two,one,and,through
19 |
20 | @param [in] str String to be deduplicated
21 | @param [in] indlm= ( ) Delimeter of the input string
22 | @param [out] outdlm= ( ) Delimiter of the output string
23 |
24 | Related Macros
25 | @li mf_trimstr.sas
26 |
27 | @version 9.2
28 | @author Allan Bowe
29 | **/
30 |
31 | %macro mf_dedup(str
32 | ,indlm=%str( )
33 | ,outdlm=%str( )
34 | )/*/STORE SOURCE*/;
35 |
36 | %local num word i pos out;
37 |
38 | %* loop over each token, searching the target for that token ;
39 | %let num=%sysfunc(countc(%superq(str),%str(&indlm)));
40 | %do i=1 %to %eval(&num+1);
41 | %let word=%scan(%superq(str),&i,%str(&indlm));
42 | %let pos=%sysfunc(indexw(&out,&word,%str(&outdlm)));
43 | %if (&pos eq 0) %then %do;
44 | %if (&i gt 1) %then %let out=&out%str(&outdlm);
45 | %let out=&out&word;
46 | %end;
47 | %end;
48 |
49 | %unquote(&out)
50 |
51 | %mend mf_dedup;
52 |
53 |
54 |
--------------------------------------------------------------------------------
/base/mf_deletefile.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Deletes a physical file, if it exists
4 | @details Usage:
5 |
6 | %mf_writefile(&sasjswork/myfile.txt,l1=some content)
7 |
8 | %mf_deletefile(&sasjswork/myfile.txt)
9 |
10 | %mf_deletefile(&sasjswork/myfile.txt)
11 |
12 |
13 | @param [in] file Full path to the target file
14 |
15 | @returns The return code from the fdelete() invocation
16 |
17 | Related Macros
18 | @li mf_deletefile.test.sas
19 | @li mf_writefile.sas
20 |
21 | @version 9.2
22 | @author Allan Bowe
23 | **/
24 |
25 | %macro mf_deletefile(file
26 | )/*/STORE SOURCE*/;
27 | %local rc fref;
28 | %let rc= %sysfunc(filename(fref,&file));
29 | %if %sysfunc(fdelete(&fref)) ne 0 %then %put %sysfunc(sysmsg());
30 | %let rc= %sysfunc(filename(fref));
31 | %mend mf_deletefile;
32 |
--------------------------------------------------------------------------------
/base/mf_existds.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file mf_existds.sas
3 | @brief Checks whether a dataset OR a view exists.
4 | @details Can be used in open code, eg as follows:
5 |
6 | %if %mf_existds(libds=work.someview) %then %put yes it does!;
7 |
8 | NOTE - some databases have case sensitive tables, for instance POSTGRES
9 | with the preserve_tab_names=yes libname setting. This may impact
10 | expected results (depending on whether you 'expect' the result to be
11 | case insensitive in this context!)
12 |
13 | @param [in] libds library.dataset
14 | @return output returns 1 or 0
15 |
16 | Related Macros
17 | @li mf_existds.test.sas
18 |
19 | @warning Untested on tables registered in metadata but not physically present
20 | @version 9.2
21 | @author Allan Bowe
22 | **/
23 |
24 | %macro mf_existds(libds
25 | )/*/STORE SOURCE*/;
26 |
27 | %if %sysfunc(exist(&libds)) ne 1 & %sysfunc(exist(&libds,VIEW)) ne 1 %then 0;
28 | %else 1;
29 |
30 | %mend mf_existds;
31 |
--------------------------------------------------------------------------------
/base/mf_existfileref.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Checks whether a fileref exists
4 | @details You can probably do without this macro as it is just a one liner.
5 | Mainly it is here as a convenient way to remember the syntax!
6 |
7 | @param [in] fref the fileref to detect
8 |
9 | @return output Returns 1 if found and 0 if not found. Note - it is possible
10 | that the fileref is found, but the file does not (yet) exist. If you need
11 | to test for this, you may as well use the fileref function directly.
12 |
13 | @version 8
14 | @author [Allan Bowe](https://www.linkedin.com/in/allanbowe/)
15 | **/
16 |
17 | %macro mf_existfileref(fref
18 | )/*/STORE SOURCE*/;
19 |
20 | %local rc;
21 | %let rc=%sysfunc(fileref(&fref));
22 | %if &rc=0 %then %do;
23 | 1
24 | %end;
25 | %else %if &rc<0 %then %do;
26 | %put &sysmacroname: Fileref &fref exists but the underlying file does not;
27 | 1
28 | %end;
29 | %else %do;
30 | 0
31 | %end;
32 |
33 | %mend mf_existfileref;
34 |
--------------------------------------------------------------------------------
/base/mf_existfunction.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Checks if a function exists
4 | @details Returns 1 if the function exists, else 0. Note that this function
5 | can be slow as it needs to open the sashelp.vfuncs table.
6 |
7 | Usage:
8 |
9 | %put %mf_existfunction(CAT);
10 | %put %mf_existfunction(DOG);
11 |
12 | Full credit to [Bart](https://sasensei.com/user/305) for the vfunc pointer
13 | and the tidy approach for pure macro data set filtering.
14 | Check out his [SAS Packages](https://github.com/yabwon/SAS_PACKAGES)
15 | framework! Where you can find the same [function](
16 | https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/baseplus.md#functionexists-macro
17 | ).
18 |
19 | @param [in] name function name
20 |
21 | @author Allan Bowe
22 | **/
23 | /** @cond */
24 | %macro mf_existfunction(name
25 | )/*/STORE SOURCE*/;
26 |
27 | %local dsid rc exist;
28 | %let dsid=%sysfunc(open(sashelp.vfunc(where=(fncname="%upcase(&name)"))));
29 | %let exist=1;
30 | %let exist=%sysfunc(fetch(&dsid, NOSET));
31 | %let rc=%sysfunc(close(&dsid));
32 |
33 | %sysevalf(0 = &exist)
34 |
35 | %mend mf_existfunction;
36 |
37 | /** @endcond */
--------------------------------------------------------------------------------
/base/mf_existvar.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Checks if a variable exists in a data set.
4 | @details Returns 0 if the variable does NOT exist, and the position of the var
5 | if it does.
6 | Usage:
7 |
8 | %put %mf_existvar(work.someds, somevar)
9 |
10 | @param [in] libds 2 part dataset or view reference
11 | @param [in] var variable name
12 |
13 | Related Macros
14 | @li mf_existvar.test.sas
15 |
16 | @version 9.2
17 | @author Allan Bowe
18 | **/
19 | /** @cond */
20 |
21 | %macro mf_existvar(libds /* 2 part dataset name */
22 | , var /* variable name */
23 | )/*/STORE SOURCE*/;
24 |
25 | %local dsid rc;
26 | %let dsid=%sysfunc(open(&libds,is));
27 |
28 | %if &dsid=0 %then %do;
29 | %put %sysfunc(sysmsg());
30 | 0
31 | %end;
32 | %else %if %length(&var)=0 %then %do;
33 | 0
34 | %let rc=%sysfunc(close(&dsid));
35 | %end;
36 | %else %do;
37 | %sysfunc(varnum(&dsid,&var))
38 | %let rc=%sysfunc(close(&dsid));
39 | %end;
40 |
41 | %mend mf_existvar;
42 |
43 | /** @endcond */
--------------------------------------------------------------------------------
/base/mf_existvarlist.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Checks if a set of variables ALL exist in a data set.
4 | @details Returns 0 if ANY of the variables do not exist, or 1 if they ALL do.
5 | Usage:
6 |
7 | %put %mf_existVarList(sashelp.class, age sex name dummyvar);
8 |
9 | @param [in] libds 2 part dataset or view reference
10 | @param [in] varlist space separated variable names
11 |
12 | @version 9.2
13 | @author Allan Bowe
14 | @cond
15 | **/
16 |
17 | %macro mf_existvarlist(libds, varlist
18 | )/*/STORE SOURCE*/;
19 |
20 | %if %str(&libds)=%str() or %str(&varlist)=%str() %then %do;
21 | %mf_abort(msg=No value provided to libds(&libds) or varlist (&varlist)!
22 | ,mac=mf_existvarlist.sas)
23 | %end;
24 |
25 | %local dsid rc i var found;
26 | %let dsid=%sysfunc(open(&libds,is));
27 |
28 | %if &dsid=0 %then %do;
29 | %put %str(WARN)ING: unable to open &libds in mf_existvarlist (&dsid);
30 | %end;
31 |
32 | %if %sysfunc(attrn(&dsid,NVARS))=0 %then %do;
33 | %put MF_EXISTVARLIST: No variables in &libds ;
34 | 0
35 | %return;
36 | %end;
37 |
38 | %else %do i=1 %to %sysfunc(countw(&varlist));
39 | %let var=%scan(&varlist,&i);
40 |
41 | %if %sysfunc(varnum(&dsid,&var))=0 %then %do;
42 | %let found=&found &var;
43 | %end;
44 | %end;
45 |
46 | %let rc=%sysfunc(close(&dsid));
47 | %if %str(&found)=%str() %then %do;
48 | 1
49 | %end;
50 | %else %do;
51 | 0
52 | %put Vars not found: &found;
53 | %end;
54 | %mend mf_existvarlist;
55 |
56 | /** @endcond */
--------------------------------------------------------------------------------
/base/mf_fmtdttm.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Returns E8601DT26.6 if compatible else DATETIME19.3
4 | @details From our experience in [Data Controller for SAS]
5 | (https://datacontroller.io) deployments, the E8601DT26.6 datetime format has
6 | the widest support when it comes to pass-through SQL queries.
7 |
8 | However, it is not supported in WPS or early versions of SAS 9 (M3 and below)
9 | when used as a datetime literal, eg:
10 |
11 | data _null_;
12 | demo="%sysfunc(datetime(),E8601DT26.6)"dt;
13 | demo=;
14 | run;
15 |
16 | This macro will therefore return DATEITME19.3 as an alternative format
17 | based on the runtime environment so that it can be used in such cases, eg:
18 |
19 | data _null_;
20 | demo="%sysfunc(datetime(),%mf_fmtdttm())"dt;
21 | demo=;
22 | run;
23 |
24 | Related Macros
25 | @li mf_fmtdttm.test.sas
26 |
27 | @author Allan Bowe
28 | **/
29 |
30 | %macro mf_fmtdttm(
31 | )/*/STORE SOURCE*/;
32 |
33 | %if "&sysver"="9.2" or "&sysver"="9.3"
34 | or ("&sysver"="9.4" and "%substr(&SYSVLONG,9,1)" le "3")
35 | or "%substr(&sysver,1,1)"="4"
36 | or "%substr(&sysver,1,1)"="5"
37 | %then %do;DATETIME19.3%end;
38 | %else %do;E8601DT26.6%end;
39 |
40 | %mend mf_fmtdttm;
41 |
42 |
43 |
--------------------------------------------------------------------------------
/base/mf_getattrc.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Returns a character attribute of a dataset.
4 | @details Can be used in open code, eg as follows:
5 |
6 | %put Dataset label = %mf_getattrc(sashelp.class,LABEL);
7 | %put Member Type = %mf_getattrc(sashelp.class,MTYPE);
8 |
9 | @param [in] libds library.dataset
10 | @param [in] attr full list in [documentation](
11 | https://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000147794.htm)
12 | @return output returns result of the attrc value supplied, or -1 and log
13 | message if err.
14 |
15 | @version 9.2
16 | @author Allan Bowe
17 | **/
18 |
19 | %macro mf_getattrc(
20 | libds
21 | ,attr
22 | )/*/STORE SOURCE*/;
23 | %local dsid rc;
24 | %let dsid=%sysfunc(open(&libds,is));
25 | %if &dsid = 0 %then %do;
26 | %put %str(WARN)ING: Cannot open %trim(&libds), system message below;
27 | %put %sysfunc(sysmsg());
28 | -1
29 | %end;
30 | %else %do;
31 | %sysfunc(attrc(&dsid,&attr))
32 | %let rc=%sysfunc(close(&dsid));
33 | %end;
34 | %mend mf_getattrc;
--------------------------------------------------------------------------------
/base/mf_getattrn.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Returns a numeric attribute of a dataset.
4 | @details Can be used in open code, eg as follows:
5 |
6 | %put Number of observations=%mf_getattrn(sashelp.class,NLOBS);
7 | %put Number of variables = %mf_getattrn(sashelp.class,NVARS);
8 |
9 | @param [in] libds library.dataset
10 | @param [in] attr Common values are NLOBS and NVARS, full list in [documentation](
11 | http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000212040.htm)
12 | @return output returns result of the attrn value supplied, or -1 and log
13 | message if err.
14 |
15 | @version 9.2
16 | @author Allan Bowe
17 | **/
18 |
19 | %macro mf_getattrn(
20 | libds
21 | ,attr
22 | )/*/STORE SOURCE*/;
23 | %local dsid rc;
24 | %let dsid=%sysfunc(open(&libds,is));
25 | %if &dsid = 0 %then %do;
26 | %put %str(WARN)ING: Cannot open %trim(&libds), system message below;
27 | %put %sysfunc(sysmsg());
28 | -1
29 | %end;
30 | %else %do;
31 | %sysfunc(attrn(&dsid,&attr))
32 | %let rc=%sysfunc(close(&dsid));
33 | %end;
34 | %mend mf_getattrn;
--------------------------------------------------------------------------------
/base/mf_getengine.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Returns the engine type of a SAS library
4 | @details Usage:
5 |
6 | %put %mf_getengine(SASHELP);
7 |
8 | returns:
9 | > V9
10 |
11 | A note is also written to the log. The credit for this macro goes to the
12 | contributors of Chris Hemedingers blog [post](
13 | http://blogs.sas.com/content/sasdummy/2013/06/04/find-a-sas-library-engine/)
14 |
15 | @param [in] libref Library reference (also accepts a 2 level libds ref).
16 |
17 | @return output returns the library engine (uppercase) for the FIRST library
18 | encountered.
19 |
20 | @warning will only return the FIRST library engine - for concatenated
21 | libraries, with different engines, inconsistent results may be encountered.
22 |
23 | @version 9.2
24 | @author Allan Bowe
25 |
26 | Related Macros
27 | @li mf_getxengine.sas
28 |
29 | **/
30 | /** @cond */
31 |
32 | %macro mf_getengine(libref
33 | )/*/STORE SOURCE*/;
34 | %local dsid engnum rc engine;
35 |
36 | /* in case the parameter is a libref.tablename, pull off just the libref */
37 | %let libref = %upcase(%scan(&libref, 1, %str(.)));
38 |
39 | %let dsid=%sysfunc(
40 | open(sashelp.vlibnam(where=(libname="%upcase(&libref)")),i)
41 | );
42 | %if (&dsid ^= 0) %then %do;
43 | %let engnum=%sysfunc(varnum(&dsid,ENGINE));
44 | %let rc=%sysfunc(fetch(&dsid));
45 | %let engine=%sysfunc(getvarc(&dsid,&engnum));
46 | %put &libref. ENGINE is &engine.;
47 | %let rc= %sysfunc(close(&dsid));
48 | %end;
49 |
50 | %upcase(&engine)
51 |
52 | %mend mf_getengine;
53 |
54 | /** @endcond */
--------------------------------------------------------------------------------
/base/mf_getfmtname.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Extracts a format name from a fully defined format
4 | @details Converts formats in like $thi3. and th13.2 $THI and TH.
5 | Usage:
6 |
7 | %put %mf_getfmtname(8.);
8 | %put %mf_getfmtname($4.);
9 | %put %mf_getfmtname(comma14.10);
10 |
11 | Returns:
12 |
13 | > W
14 | > $CHAR
15 | > COMMA
16 |
17 | Note that system defaults are inferred from the values provided.
18 |
19 | @param [in] fmt The fully defined format. If left blank, nothing is returned.
20 |
21 | @returns The name (without width or decimal) of the format.
22 |
23 | @version 9.2
24 | @author Allan Bowe
25 |
26 | **/
27 |
28 | %macro mf_getfmtname(fmt
29 | )/*/STORE SOURCE*/ /minoperator mindelimiter=' ';
30 |
31 | %local out dsid nvars x rc fmt;
32 |
33 | /* extract actual format name from the format definition */
34 | %let fmt=%scan(&fmt,1,.);
35 | %do %while(%substr(&fmt,%length(&fmt),1) in 1 2 3 4 5 6 7 8 9 0);
36 | %if %length(&fmt)=1 %then %let fmt=W;
37 | %else %let fmt=%substr(&fmt,1,%length(&fmt)-1);
38 | %end;
39 |
40 | %if &fmt=$ %then %let fmt=$CHAR;
41 |
42 | /* send them out without spaces or quote markers */
43 | %do;%unquote(%upcase(&fmt))%end;
44 | %mend mf_getfmtname;
--------------------------------------------------------------------------------
/base/mf_getgitbranch.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Retrieves the current branch from a local GIT repo
4 | @details In a local git repository, the current branch is always available in
5 | the `.git/HEAD` file in a format like this: `ref: refs/heads/master`
6 |
7 | This macro simply reads the file and returns the last word (eg `master`).
8 |
9 | Example usage:
10 |
11 | %let gitdir=%sysfunc(pathname(work))/core;
12 | %let repo=https://github.com/sasjs/core;
13 | %put source clone rc=%sysfunc(GITFN_CLONE(&repo,&gitdir));
14 |
15 | %put The current branch is %mf_getgitbranch(&gitdir);
16 |
17 | @param [in] gitdir The directory containing the GIT repository
18 |
19 | SAS Macros
20 | @li mf_readfile.sas
21 |
22 | Related Macros
23 | @li mp_gitadd.sas
24 | @li mp_gitlog.sas
25 | @li mp_gitreleaseinfo.sas
26 | @li mp_gitstatus.sas
27 |
28 | @version 9.2
29 | @author Allan Bowe
30 | **/
31 |
32 | %macro mf_getgitbranch(gitdir
33 | )/*/STORE SOURCE*/;
34 |
35 | %scan(%mf_readfile(&gitdir/.git/HEAD),-1)
36 |
37 | %mend mf_getgitbranch;
38 |
--------------------------------------------------------------------------------
/base/mf_getkeyvalue.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief retrieves a key value pair from a control dataset
4 | @details By default, control dataset is work.mp_setkeyvalue. Usage:
5 |
6 | %mp_setkeyvalue(someindex,22,type=N)
7 | %put %mf_getkeyvalue(someindex)
8 |
9 |
10 | @param [in] key Provide a key on which to perform the lookup
11 | @param [in] libds= (work.mp_setkeyvalue) The library.dataset which holds the
12 | parameters
13 |
14 | @version 9.2
15 | @author Allan Bowe
16 | **/
17 |
18 | %macro mf_getkeyvalue(key,libds=work.mp_setkeyvalue
19 | )/*/STORE SOURCE*/;
20 | %local ds dsid key valc valn type rc;
21 | %let dsid=%sysfunc(open(&libds(where=(key="&key"))));
22 | %syscall set(dsid);
23 | %let rc = %sysfunc(fetch(&dsid));
24 | %let rc = %sysfunc(close(&dsid));
25 |
26 | %if &type=N %then %do;
27 | &valn
28 | %end;
29 | %else %if &type=C %then %do;
30 | &valc
31 | %end;
32 | %else %put %str(ERR)OR: Unable to find key &key in ds &libds;
33 | %mend mf_getkeyvalue;
--------------------------------------------------------------------------------
/base/mf_getschema.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file mf_getschema.sas
3 | @brief Returns the database schema of a SAS library
4 | @details Usage:
5 |
6 | %put %mf_getschema(MYDB);
7 |
8 | returns:
9 | > dbo
10 |
11 | @param [in] libref Library reference (also accepts a 2 level libds ref).
12 |
13 | @return output returns the library schema for the FIRST library encountered
14 |
15 | @warning will only return the FIRST library schema - for concatenated
16 | libraries, with different schemas, inconsistent results may be encountered.
17 |
18 | @version 9.2
19 | @author Allan Bowe
20 | @cond
21 | **/
22 |
23 | %macro mf_getschema(libref
24 | )/*/STORE SOURCE*/;
25 | %local dsid vnum rc schema;
26 | /* in case the parameter is a libref.tablename, pull off just the libref */
27 | %let libref = %upcase(%scan(&libref, 1, %str(.)));
28 | %let dsid=%sysfunc(open(sashelp.vlibnam(where=(
29 | libname="%upcase(&libref)" and sysname='Schema/Owner'
30 | )),i));
31 | %if (&dsid ^= 0) %then %do;
32 | %let vnum=%sysfunc(varnum(&dsid,SYSVALUE));
33 | %let rc=%sysfunc(fetch(&dsid));
34 | %let schema=%sysfunc(getvarc(&dsid,&vnum));
35 | %put &libref. schema is &schema.;
36 | %let rc= %sysfunc(close(&dsid));
37 | %end;
38 |
39 | &schema
40 |
41 | %mend mf_getschema;
42 |
43 | /** @endcond */
44 |
--------------------------------------------------------------------------------
/base/mf_getuniquename.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file mf_getuniquename.sas
3 | @brief Returns a shortened (32 char) GUID as a valid SAS name
4 | @details Use as follows:
5 |
6 | %let myds=%mf_getuniquename();
7 | %put &=myds;
8 |
9 | which returns:
10 |
11 | > MCc59c750610321d4c8bf75faadbcd22
12 |
13 | @param [in] prefix= (MC) Sets a prefix for the new name
14 |
15 | @version 9.3
16 | @author Allan Bowe
17 | **/
18 |
19 |
20 | %macro mf_getuniquename(prefix=MC);
21 | &prefix.%substr(%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32-%length(&prefix))
22 | %mend mf_getuniquename;
--------------------------------------------------------------------------------
/base/mf_getuser.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Returns a userid according to session context
4 | @details In a workspace session, a user is generally represented by
5 | &sysuserid
or SYS_COMPUTE_SESSION_OWNER
if it exists.
6 | In a Stored Process session, &sysuserid
7 | resolves to a system account (default=sassrv) and instead there are several
8 | metadata username variables to choose from (_metauser, _metaperson
9 | ,_username, _secureusername). The OS account is represented by
10 | _secureusername
whilst the metadata account is under
11 | _metaperson
.
12 |
13 | %let user= %mf_getUser();
14 | %put &user;
15 |
16 | @return SYSUSERID (if workspace server)
17 | @return _METAPERSON (if stored process server)
18 | @return SYS_COMPUTE_SESSION_OWNER (if Viya compute session)
19 |
20 | @version 9.2
21 | @author Allan Bowe
22 | **/
23 |
24 | %macro mf_getuser(
25 | )/*/STORE SOURCE*/;
26 | %local user;
27 |
28 | %if %symexist(_sasjs_username) %then %let user=&_sasjs_username;
29 | %else %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %do;
30 | %let user=&SYS_COMPUTE_SESSION_OWNER;
31 | %end;
32 | %else %if %symexist(_metaperson) %then %do;
33 | %if %length(&_metaperson)=0 %then %let user=&sysuserid;
34 | /* sometimes SAS will add @domain extension - remove for consistency */
35 | /* but be sure to quote in case of usernames with commas */
36 | %else %let user=%unquote(%scan(%quote(&_metaperson),1,@));
37 | %end;
38 | %else %let user=&sysuserid;
39 |
40 | %quote(&user)
41 |
42 | %mend mf_getuser;
43 |
--------------------------------------------------------------------------------
/base/mf_getvalue.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Retrieves a value from a dataset. If no filter supplied, then first
4 | record is used.
5 | @details Be sure to %quote()
your where clause. Example usage:
6 |
7 | %put %mf_getvalue(sashelp.class,name,filter=%quote(age=15));
8 | %put %mf_getvalue(sashelp.class,name);
9 |
10 | SAS Macros
11 | @li mf_getattrn.sas
12 |
13 | Related Macros
14 | @li mp_setkeyvalue.sas
15 |
16 | @param [in] libds dataset to query
17 | @param [in] variable the variable which contains the value to return.
18 | @param [in] filter= (1) contents of where clause
19 |
20 | @version 9.2
21 | @author Allan Bowe
22 | **/
23 |
24 | %macro mf_getvalue(libds,variable,filter=1
25 | )/*/STORE SOURCE*/;
26 | %if %mf_getattrn(&libds,NLOBS)>0 %then %do;
27 | %local dsid rc &variable;
28 | %let dsid=%sysfunc(open(&libds(where=(&filter))));
29 | %syscall set(dsid);
30 | %let rc = %sysfunc(fetch(&dsid));
31 | %let rc = %sysfunc(close(&dsid));
32 |
33 | %trim(&&&variable)
34 |
35 | %end;
36 | %mend mf_getvalue;
--------------------------------------------------------------------------------
/base/mf_getvarcount.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Returns number of variables in a dataset
4 | @details Useful to identify those renagade datasets that have no columns!
5 | Can also be used to count for numeric, or character columns
6 |
7 | %put Number of Variables=%mf_getvarcount(sashelp.class);
8 | %put Character Variables=%mf_getvarcount(sashelp.class,typefilter=C);
9 | %put Numeric Variables = %mf_getvarcount(sashelp.class,typefilter=N);
10 |
11 | returns:
12 | > Number of Variables=4
13 |
14 |
15 | @param [in] libds Two part dataset (or view) reference.
16 | @param [in] typefilter= (A) Filter for certain types of column. Valid values:
17 | @li A Count All columns
18 | @li C Count Character columns only
19 | @li N Count Numeric columns only
20 |
21 | @version 9.2
22 | @author Allan Bowe
23 |
24 | **/
25 |
26 | %macro mf_getvarcount(libds,typefilter=A
27 | )/*/STORE SOURCE*/;
28 | %local dsid nvars rc outcnt x;
29 | %let dsid=%sysfunc(open(&libds));
30 | %let nvars=.;
31 | %let outcnt=0;
32 | %let typefilter=%upcase(&typefilter);
33 | %if &dsid %then %do;
34 | %let nvars=%sysfunc(attrn(&dsid,NVARS));
35 | %if &typefilter=A %then %let outcnt=&nvars;
36 | %else %if &nvars>0 %then %do x=1 %to &nvars;
37 | /* increment based on variable type */
38 | %if %sysfunc(vartype(&dsid,&x))=&typefilter %then %do;
39 | %let outcnt=%eval(&outcnt+1);
40 | %end;
41 | %end;
42 | %let rc=%sysfunc(close(&dsid));
43 | %end;
44 | %else %do;
45 | %put unable to open &libds (rc=&dsid);
46 | %let rc=%sysfunc(close(&dsid));
47 | %end;
48 | &outcnt
49 | %mend mf_getvarcount;
--------------------------------------------------------------------------------
/base/mf_getvarlen.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Returns the length of a variable
4 | @details Uses varlen function to identify the length of a particular variable.
5 | Usage:
6 |
7 | data test;
8 | format str $1. num datetime19.;
9 | stop;
10 | run;
11 | %put %mf_getVarLen(test,str);
12 | %put %mf_getVarLen(work.test,num);
13 | %put %mf_getVarLen(test,renegade);
14 |
15 | returns:
16 |
17 | 1
18 | 8
19 | NOTE: Variable renegade does not exist in test
20 |
21 | @param [in] libds Two part dataset (or view) reference.
22 | @param [in] var Variable name for which a length should be returned
23 | @returns outputs length
24 |
25 | @author Allan Bowe
26 | @version 9.2
27 |
28 | **/
29 |
30 | %macro mf_getVarLen(libds /* two level ds name */
31 | , var /* variable name from which to return the length */
32 | )/*/STORE SOURCE*/;
33 | %local dsid vnum vlen rc;
34 | /* Open dataset */
35 | %let dsid = %sysfunc(open(&libds));
36 | %if &dsid > 0 %then %do;
37 | /* Get variable number */
38 | %let vnum = %sysfunc(varnum(&dsid, &var));
39 | /* Get variable format */
40 | %if(&vnum > 0) %then %let vlen = %sysfunc(varlen(&dsid, &vnum));
41 | %else %do;
42 | %put NOTE: Variable &var does not exist in &libds;
43 | %let vlen = %str( );
44 | %end;
45 | %end;
46 | %else %do;
47 | %put &sysmacroname: dataset &libds not opened! (rc=&dsid);
48 | %put &sysmacroname: %sysfunc(sysmsg());
49 | %return;
50 | %end;
51 |
52 | /* Close dataset */
53 | %let rc = %sysfunc(close(&dsid));
54 | /* Return variable format */
55 | &vlen
56 | %mend mf_getVarLen;
--------------------------------------------------------------------------------
/base/mf_getvarnum.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Returns the position of a variable in dataset (varnum attribute).
4 | @details Uses varnum function to determine position.
5 |
6 | Usage:
7 |
8 | data work.test;
9 | format str $1. num datetime19.;
10 | stop;
11 | run;
12 | %put %mf_getVarNum(work.test,str);
13 | %put %mf_getVarNum(work.test,num);
14 | %put %mf_getVarNum(work.test,renegade);
15 |
16 | returns:
17 |
18 | > 1
19 |
20 | > 2
21 |
22 | > NOTE: Variable renegade does not exist in test
23 |
24 | @param [in] libds Two part dataset (or view) reference.
25 | @param [in] var Variable name for which a position should be returned
26 |
27 | @author Allan Bowe
28 | @version 9.2
29 |
30 | **/
31 |
32 | %macro mf_getVarNum(libds /* two level ds name */
33 | , var /* variable name from which to return the format */
34 | )/*/STORE SOURCE*/;
35 | %local dsid vnum rc;
36 | /* Open dataset */
37 | %let dsid = %sysfunc(open(&libds));
38 | %if &dsid > 0 %then %do;
39 | /* Get variable number */
40 | %let vnum = %sysfunc(varnum(&dsid, &var));
41 | %if(&vnum <= 0) %then %do;
42 | %put NOTE: Variable &var does not exist in &libds;
43 | %let vnum = %str( );
44 | %end;
45 | %end;
46 | %else %do;
47 | %put &sysmacroname: dataset &libds not opened! (rc=&dsid);
48 | %put &sysmacroname: %sysfunc(sysmsg());
49 | %return;
50 | %end;
51 |
52 | /* Close dataset */
53 | %let rc = %sysfunc(close(&dsid));
54 |
55 | /* Return variable number */
56 | &vnum.
57 |
58 | %mend mf_getVarNum;
--------------------------------------------------------------------------------
/base/mf_getvartype.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Returns variable type - Character (C) or Numeric (N)
4 | @details
5 | Usage:
6 |
7 | data test;
8 | length str $1. num 8.;
9 | stop;
10 | run;
11 | %put %mf_getvartype(test,str);
12 | %put %mf_getvartype(work.test,num);
13 |
14 |
15 |
16 | @param [in] libds Two part dataset (or view) reference.
17 | @param [in] var the variable name to be checked
18 | @return output returns C or N depending on variable type. If variable
19 | does not exist then a blank is returned and a note is written to the log.
20 |
21 | @version 9.2
22 | @author Allan Bowe
23 |
24 | **/
25 |
26 | %macro mf_getvartype(libds /* two level name */
27 | , var /* variable name from which to return the type */
28 | )/*/STORE SOURCE*/;
29 | %local dsid vnum vtype rc;
30 | /* Open dataset */
31 | %let dsid = %sysfunc(open(&libds));
32 | %if &dsid. > 0 %then %do;
33 | /* Get variable number */
34 | %let vnum = %sysfunc(varnum(&dsid, &var));
35 | /* Get variable type (C/N) */
36 | %if(&vnum. > 0) %then %let vtype = %sysfunc(vartype(&dsid, &vnum.));
37 | %else %do;
38 | %put NOTE: Variable &var does not exist in &libds;
39 | %let vtype = %str( );
40 | %end;
41 | %end;
42 | %else %do;
43 | %put &sysmacroname: dataset &libds not opened! (rc=&dsid);
44 | %put &sysmacroname: %sysfunc(sysmsg());
45 | %return;
46 | %end;
47 |
48 | /* Close dataset */
49 | %let rc = %sysfunc(close(&dsid));
50 | /* Return variable type */
51 | &vtype
52 | %mend mf_getvartype;
--------------------------------------------------------------------------------
/base/mf_getxengine.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Returns the engine type of a SAS fileref
4 | @details Queries sashelp.vextfl to get the xengine value.
5 | Usage:
6 |
7 | filename feng temp;
8 | %put %mf_getxengine(feng);
9 |
10 | returns:
11 | > TEMP
12 |
13 | @param [in] fref The fileref to check
14 |
15 | @returns The XENGINE value in sashelp.vextfl or 0 if not found.
16 |
17 | @version 9.2
18 | @author Allan Bowe
19 |
20 | Related Macros
21 | @li mf_getengine.sas
22 |
23 | **/
24 |
25 | %macro mf_getxengine(fref
26 | )/*/STORE SOURCE*/;
27 | %local dsid engnum rc engine;
28 |
29 | %let dsid=%sysfunc(
30 | open(sashelp.vextfl(where=(fileref="%upcase(&fref)")),i)
31 | );
32 | %if (&dsid ^= 0) %then %do;
33 | %let engnum=%sysfunc(varnum(&dsid,XENGINE));
34 | %let rc=%sysfunc(fetch(&dsid));
35 | %let engine=%sysfunc(getvarc(&dsid,&engnum));
36 | %* put &fref. ENGINE is &engine.;
37 | %let rc= %sysfunc(close(&dsid));
38 | %end;
39 | %else %let engine=0;
40 |
41 | &engine
42 |
43 | %mend mf_getxengine;
44 |
--------------------------------------------------------------------------------
/base/mf_increment.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Increments a macro variable
4 | @details Useful outside of do-loops - will increment a macro variable every
5 | time it is called.
6 |
7 | Example:
8 |
9 | %let cnt=1;
10 | %put We have run %mf_increment(cnt) lines;
11 | %put Now we have run %mf_increment(cnt) lines;
12 | %put There are %mf_increment(cnt) lines in total;
13 |
14 | @param [in] macro_name The name of the macro variable to increment
15 | @param [in] incr= (1) The amount to add or subtract to the macro
16 |
17 | Related Files
18 | @li mf_increment.test.sas
19 |
20 | **/
21 |
22 | %macro mf_increment(macro_name,incr=1);
23 |
24 | /* iterate the value */
25 | %let ¯o_name=%eval(&&¯o_name+&incr);
26 | /* return the value */
27 | &&¯o_name
28 |
29 | %mend mf_increment;
30 |
--------------------------------------------------------------------------------
/base/mf_isblank.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file mf_isblank.sas
3 | @brief Checks whether a macro variable is empty (blank)
4 | @details Simply performs:
5 |
6 | %sysevalf(%superq(param)=,boolean)
7 |
8 | Usage:
9 |
10 | %put %mf_isblank(&var);
11 |
12 | inspiration:
13 | https://support.sas.com/resources/papers/proceedings09/022-2009.pdf
14 |
15 | @param [in] Param VALUE to be checked
16 |
17 | @return output returns 1 (if blank) else 0
18 |
19 | @version 9.2
20 | **/
21 |
22 | %macro mf_isblank(param
23 | )/*/STORE SOURCE*/;
24 |
25 | %sysevalf(%superq(param)=,boolean)
26 |
27 | %mend mf_isblank;
--------------------------------------------------------------------------------
/base/mf_isdir.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Checks whether a path is a valid directory
4 | @details
5 | Usage:
6 |
7 | %let isdir=%mf_isdir(/tmp);
8 |
9 | With thanks and full credit to Andrea Defronzo -
10 | https://www.linkedin.com/in/andrea-defronzo-b1a47460/
11 |
12 | @param [in] path Full path of the file/directory to be checked
13 |
14 | @return output returns 1 if path is a directory, 0 if it is not
15 |
16 | @version 9.2
17 | **/
18 |
19 | %macro mf_isdir(path
20 | )/*/STORE SOURCE*/;
21 | %local rc did is_directory fref_t;
22 |
23 | %let is_directory = 0;
24 | %let rc = %sysfunc(filename(fref_t, %superq(path)));
25 | %let did = %sysfunc(dopen(&fref_t.));
26 | %if &did. ^= 0 %then %do;
27 | %let is_directory = 1;
28 | %let rc = %sysfunc(dclose(&did.));
29 | %end;
30 | %let rc = %sysfunc(filename(fref_t));
31 |
32 | &is_directory
33 |
34 | %mend mf_isdir;
--------------------------------------------------------------------------------
/base/mf_isint.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Returns 1 if the variable contains only digits 0-9, else 0
4 | @details Note that numerics containing any punctuation (including decimals
5 | or exponents) will be flagged zero.
6 |
7 | If you'd like support for this, then do raise an issue (or even better, a
8 | pull request!)
9 |
10 | Usage:
11 |
12 | %put %mf_isint(1) returns 1;
13 | %put %mf_isint(1.1) returns 0;
14 | %put %mf_isint(%str(1,1)) returns 0;
15 |
16 | @param [in] arg input value to check
17 |
18 | @version 9.2
19 | **/
20 |
21 | %macro mf_isint(arg
22 | )/*/STORE SOURCE*/;
23 |
24 | /* blank val is not an integer */
25 | %if "&arg"="" %then %do;0%return;%end;
26 |
27 | /* remove minus sign if exists */
28 | %local val;
29 | %if "%substr(%str(&arg),1,1)"="-" %then %let val=%substr(%str(&arg),2);
30 | %else %let val=&arg;
31 |
32 | /* check remaining chars */
33 | %if %sysfunc(findc(%str(&val),,kd)) %then %do;0%end;
34 | %else %do;1%end;
35 |
36 | %mend mf_isint;
37 |
--------------------------------------------------------------------------------
/base/mf_islibds.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Checks whether a string follows correct library.dataset format
4 | @details Many macros in the core library accept a library.dataset parameter
5 | referred to as 'libds'. This macro validates the structure of that parameter,
6 | eg:
7 |
8 | @li 8 character libref?
9 | @li 32 character dataset?
10 | @li contains a period?
11 |
12 | It does NOT check whether the dataset exists, or if the library is assigned.
13 |
14 | Usage:
15 |
16 | %put %mf_islibds(work.something)=1;
17 | %put %mf_islibds(nolib)=0;
18 | %put %mf_islibds(badlibref.ds)=0;
19 | %put %mf_islibds(w.t.f)=0;
20 |
21 | @param [in] libds The string to be checked
22 |
23 | @return output Returns 1 if libds is valid, 0 if it is not
24 |
25 | Related Macros
26 | @li mf_islibds.test.sas
27 | @li mp_validatecol.sas
28 |
29 | @version 9.2
30 | **/
31 |
32 | %macro mf_islibds(libds
33 | )/*/STORE SOURCE*/;
34 |
35 | %local regex;
36 | %let regex=%sysfunc(prxparse(%str(/^[_a-z]\w{0,7}\.[_a-z]\w{0,31}$/i)));
37 |
38 | %sysfunc(prxmatch(®ex,&libds))
39 |
40 | %mend mf_islibds;
--------------------------------------------------------------------------------
/base/mf_loc.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Returns physical location of various SAS items
4 | @details Returns location of the PlatformObjectFramework tools
5 | Usage:
6 |
7 | %put %mf_loc(POF); %*location of PlatformObjectFramework tools;
8 |
9 | @param [in] loc The item to locate, eg:
10 | @li PLAATFORMOBJECTFRAMEWORK (or POF)
11 | @li VIYACONFG
12 |
13 | @version 9.2
14 | @author Allan Bowe
15 | **/
16 |
17 | %macro mf_loc(loc);
18 | %let loc=%upcase(&loc);
19 | %local root;
20 |
21 | %if &loc=POF or &loc=PLATFORMOBJECTFRAMEWORK %then %do;
22 | %let root=%sysget(SASROOT);
23 | %let root=%substr(&root,1,%index(&root,SASFoundation)-2);
24 | %let root=&root/SASPlatformObjectFramework/&sysver;
25 | %put Batch tools located at: &root;
26 | &root
27 | %end;
28 | %else %if &loc=VIYACONFIG %then %do;
29 | %let root=/opt/sas/viya/config;
30 | %put Viya Config located at: &root;
31 | &root
32 | %end;
33 |
34 | %mend mf_loc;
35 |
--------------------------------------------------------------------------------
/base/mf_mval.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file mf_mval.sas
3 | @brief Returns a macro variable value if the variable exists
4 | @details
5 | Use this macro to avoid repetitive use of `%if %symexist(MACVAR) %then`
6 | type logic.
7 | Usage:
8 |
9 | %if %mf_mval(maynotexist)=itdid %then %do;
10 |
11 | @param [in] var The macro variable NAME to return the (possible) value for
12 |
13 | @version 9.2
14 | @author Allan Bowe
15 | **/
16 |
17 | %macro mf_mval(var);
18 | %if %symexist(&var) %then %do;
19 | %superq(&var)
20 | %end;
21 | %mend mf_mval;
22 |
--------------------------------------------------------------------------------
/base/mf_nobs.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Returns number of logical (undeleted) observations.
4 | @details Beware - will not work on external database tables!
5 | Is just a convenience macro for calling %mf_getattrn()
.
6 |
7 | %put Number of observations=%mf_nobs(sashelp.class);
8 |
9 | SAS Macros
10 | @li mf_getattrn.sas
11 |
12 | @param [in] libds library.dataset
13 |
14 | @return output returns result of the attrn value supplied, or log message
15 | if err.
16 |
17 |
18 | @version 9.2
19 | @author Allan Bowe
20 |
21 | **/
22 |
23 | %macro mf_nobs(libds
24 | )/*/STORE SOURCE*/;
25 | %mf_getattrn(&libds,NLOBS)
26 | %mend mf_nobs;
--------------------------------------------------------------------------------
/base/mf_readfile.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Reads the first line of a file using pure macro
4 | @details Reads the first line of a file and returns it. Future versions may
5 | read each line into a macro variable array.
6 |
7 | Generally, reading data into macro variables is not great as certain
8 | nonprintable characters (such as CR, LF) may be dropped in the conversion.
9 |
10 | Usage:
11 |
12 | %mf_writefile(&sasjswork/myfile.txt,l1=some content,l2=more content)
13 |
14 | %put %mf_readfile(&sasjswork/myfile.txt);
15 |
16 |
17 | @param [in] fpath Full path to file to be read
18 |
19 | Related Macros
20 | @li mf_deletefile.sas
21 | @li mf_writefile.sas
22 | @li mf_readfile.test.sas
23 |
24 | @version 9.2
25 | @author Allan Bowe
26 | **/
27 | /** @cond */
28 |
29 | %macro mf_readfile(fpath
30 | )/*/STORE SOURCE*/;
31 | %local fref rc fid fcontent;
32 |
33 | /* check file exists */
34 | %if %sysfunc(filename(fref,&fpath)) ne 0 %then %do;
35 | %put &=fref &=fpath;
36 | %put %str(ERR)OR: %sysfunc(sysmsg());
37 | %return;
38 | %end;
39 |
40 | %let fid=%sysfunc(fopen(&fref,I));
41 |
42 | %if &fid=0 %then %do;
43 | %put %str(ERR)OR: %sysfunc(sysmsg());
44 | %return;
45 | %end;
46 |
47 | %if %sysfunc(fread(&fid)) = 0 %then %do;
48 | %let rc=%sysfunc(fget(&fid,fcontent,65534));
49 | &fcontent
50 | %end;
51 |
52 | /*
53 | %do %while(%sysfunc(fread(&fid)) = 0);
54 | %let rc=%sysfunc(fget(&fid,fcontent,65534));
55 | &fcontent
56 | %end;
57 | */
58 |
59 | %let rc=%sysfunc(fclose(&fid));
60 | %let rc=%sysfunc(filename(&fref));
61 |
62 | %mend mf_readfile;
63 | /** @endcond */
64 |
--------------------------------------------------------------------------------
/base/mf_trimstr.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file mf_trimstr.sas
3 | @brief Removes character(s) from the end, if they exist
4 | @details If the designated characters exist at the end of the string, they
5 | are removed
6 |
7 | %put %mf_trimstr(/blah/,/); * /blah;
8 | %put %mf_trimstr(/blah/,h); * /blah/;
9 | %put %mf_trimstr(/blah/,h/);* /bla;
10 |
11 | SAS Macros
12 |
13 |
14 | @param [in] basestr The string to be modified
15 | @param [in] trimstr The string to be removed from the end of `basestr`, if it
16 | exists
17 |
18 | @return output returns result with the value of `trimstr` removed from the end
19 |
20 |
21 | @version 9.2
22 | @author Allan Bowe
23 |
24 | **/
25 |
26 | %macro mf_trimstr(basestr,trimstr);
27 | %local baselen trimlen trimval;
28 |
29 | /* return if basestr is shorter than trimstr (or 0) */
30 | %let baselen=%length(%superq(basestr));
31 | %let trimlen=%length(%superq(trimstr));
32 | %if &baselen < &trimlen or &baselen=0 %then %return;
33 |
34 | /* obtain the characters from the end of basestr */
35 | %let trimval=%qsubstr(%superq(basestr)
36 | ,%length(%superq(basestr))-&trimlen+1
37 | ,&trimlen);
38 |
39 | /* compare and if matching, chop it off! */
40 | %if %superq(basestr)=%superq(trimstr) %then %do;
41 | %return;
42 | %end;
43 | %else %if %superq(trimval)=%superq(trimstr) %then %do;
44 | %qsubstr(%superq(basestr),1,%length(%superq(basestr))-&trimlen)
45 | %end;
46 | %else %do;
47 | &basestr
48 | %end;
49 |
50 | %mend mf_trimstr;
--------------------------------------------------------------------------------
/base/mf_uid.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Creates a unique ID based on system time in friendly format
4 | @details format = YYYYMMDD_HHMMSSmmm__<3randomDigits>
5 |
6 | %put %mf_uid();
7 |
8 | @version 9.3
9 | @author Allan Bowe
10 |
11 | **/
12 |
13 | %macro mf_uid(
14 | )/*/STORE SOURCE*/;
15 | %local today now;
16 | %let today=%sysfunc(today(),yymmddn8.);
17 | %let now=%sysfunc(compress(%sysfunc(time(),tod12.3),:.));
18 |
19 | &today._&now._&sysjobid._%sysevalf(%sysfunc(ranuni(0))*999,CEIL)
20 |
21 | %mend mf_uid;
--------------------------------------------------------------------------------
/base/mf_wordsinstr1andstr2.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Returns words that are in both string 1 and string 2
4 | @details Compares two space separated strings and returns the words that are
5 | in both.
6 | Usage:
7 |
8 | %put %mf_wordsInStr1andStr2(
9 | Str1=blah sss blaaah brah bram boo
10 | ,Str2= blah blaaah brah ssss
11 | );
12 |
13 | returns:
14 | > blah blaaah brah
15 |
16 | @param [in] str1= () string containing words to extract
17 | @param [in] str2= () used to compare with the extract string
18 |
19 | @warning CASE SENSITIVE!
20 |
21 | @version 9.2
22 | @author Allan Bowe
23 |
24 | **/
25 |
26 | %macro mf_wordsInStr1andStr2(
27 | Str1= /* string containing words to extract */
28 | ,Str2= /* used to compare with the extract string */
29 | )/*/STORE SOURCE*/;
30 |
31 | %local count_base count_extr i i2 extr_word base_word match outvar;
32 | %if %length(&str1)=0 or %length(&str2)=0 %then %do;
33 | %put base string (str1)= &str1;
34 | %put compare string (str2) = &str2;
35 | %return;
36 | %end;
37 | %let count_base=%sysfunc(countw(&Str2));
38 | %let count_extr=%sysfunc(countw(&Str1));
39 |
40 | %do i=1 %to &count_extr;
41 | %let extr_word=%scan(&Str1,&i,%str( ));
42 | %let match=0;
43 | %do i2=1 %to &count_base;
44 | %let base_word=%scan(&Str2,&i2,%str( ));
45 | %if &extr_word=&base_word %then %let match=1;
46 | %end;
47 | %if &match=1 %then %let outvar=&outvar &extr_word;
48 | %end;
49 |
50 | &outvar
51 |
52 | %mend mf_wordsInStr1andStr2;
53 |
54 |
--------------------------------------------------------------------------------
/base/mf_wordsinstr1butnotstr2.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Returns words that are in string 1 but not in string 2
4 | @details Compares two space separated strings and returns the words that are
5 | in the first but not in the second.
6 |
7 | Note - case sensitive!
8 |
9 | Usage:
10 |
11 | %let x= %mf_wordsInStr1ButNotStr2(
12 | Str1=blah sss blaaah brah bram boo
13 | ,Str2= blah blaaah brah ssss
14 | );
15 |
16 | returns:
17 | > sss bram boo
18 |
19 | @param [in] str1= () String containing words to extract
20 | @param [in] str2= () Used to compare with the extract string
21 |
22 | @version 9.2
23 | @author Allan Bowe
24 |
25 | **/
26 |
27 | %macro mf_wordsInStr1ButNotStr2(
28 | Str1= /* string containing words to extract */
29 | ,Str2= /* used to compare with the extract string */
30 | )/*/STORE SOURCE*/;
31 |
32 | %local count_base count_extr i i2 extr_word base_word match outvar;
33 | %if %length(&str1)=0 or %length(&str2)=0 %then %do;
34 | %put base string (str1)= &str1;
35 | %put compare string (str2) = &str2;
36 | %return;
37 | %end;
38 | %let count_base=%sysfunc(countw(&Str2));
39 | %let count_extr=%sysfunc(countw(&Str1));
40 |
41 | %do i=1 %to &count_extr;
42 | %let extr_word=%scan(&Str1,&i,%str( ));
43 | %let match=0;
44 | %do i2=1 %to &count_base;
45 | %let base_word=%scan(&Str2,&i2,%str( ));
46 | %if &extr_word=&base_word %then %let match=1;
47 | %end;
48 | %if &match=0 %then %let outvar=&outvar &extr_word;
49 | %end;
50 |
51 | &outvar
52 |
53 | %mend mf_wordsInStr1ButNotStr2;
54 |
55 |
--------------------------------------------------------------------------------
/base/mp_appendfile.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Append (concatenate) two or more files.
4 | @details Will append one more more `appendrefs` (filerefs) to a `baseref`.
5 | Uses a binary mechanism, so will work with any file type. For that reason -
6 | use with care! And supply your own trailing carriage returns in each file..
7 |
8 | Usage:
9 |
10 | filename tmp1 temp;
11 | filename tmp2 temp;
12 | filename tmp3 temp;
13 | data _null_; file tmp1; put 'base file';
14 | data _null_; file tmp2; put 'append1';
15 | data _null_; file tmp3; put 'append2';
16 | run;
17 | %mp_appendfile(baseref=tmp1, appendrefs=tmp2 tmp3)
18 |
19 |
20 | @param [in] baseref= (0) Fileref of the base file (should exist)
21 | @param [in] appendrefs= (0) One or more filerefs to be appended to the base
22 | fileref. Space separated.
23 |
24 | @version 9.2
25 | @author Allan Bowe, source: https://github.com/sasjs/core
26 |
27 | SAS Macros
28 | @li mp_abort.sas
29 | @li mp_binarycopy.sas
30 |
31 |
32 | **/
33 |
34 | %macro mp_appendfile(
35 | baseref=0,
36 | appendrefs=0
37 | )/*/STORE SOURCE*/;
38 |
39 | %mp_abort(iftrue= (&baseref=0)
40 | ,mac=&sysmacroname
41 | ,msg=%str(Baseref NOT specified!)
42 | )
43 | %mp_abort(iftrue= (&appendrefs=0)
44 | ,mac=&sysmacroname
45 | ,msg=%str(Appendrefs NOT specified!)
46 | )
47 |
48 | %local i;
49 | %do i=1 %to %sysfunc(countw(&appendrefs));
50 | %mp_abort(iftrue= (&syscc>0)
51 | ,mac=&sysmacroname
52 | ,msg=%str(syscc=&syscc)
53 | )
54 | %mp_binarycopy(inref=%scan(&appendrefs,&i), outref=&baseref, mode=APPEND)
55 | %end;
56 |
57 | %mend mp_appendfile;
--------------------------------------------------------------------------------
/base/mp_assert.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Generic assertion
4 | @details Useful in the context of writing sasjs tests. The results of the
5 | test are _appended_ to the &outds. table.
6 |
7 | Example usage:
8 |
9 | %mp_assert(iftrue=(1=1),
10 | desc=Obviously true
11 | )
12 |
13 | %mp_assert(iftrue=(1=0),
14 | desc=Will fail
15 | )
16 |
17 | @param [in] iftrue= (1=1) A condition where, if true, the test is a PASS.
18 | Else, the test is a fail.
19 |
20 | @param [in] desc= (Testing observations) The user provided test description
21 | @param [out] outds= (work.test_results) The output dataset to contain the
22 | results. If it does not exist, it will be created, with the following format:
23 | |TEST_DESCRIPTION:$256|TEST_RESULT:$4|TEST_COMMENTS:$256|
24 | |---|---|---|
25 | |User Provided description|PASS|Dataset &inds contained ALL columns|
26 |
27 | @version 9.2
28 | @author Allan Bowe
29 |
30 | **/
31 |
32 | %macro mp_assert(iftrue=(1=1),
33 | desc=0,
34 | outds=work.test_results
35 | )/*/STORE SOURCE*/;
36 |
37 | data ;
38 | length test_description $256 test_result $4 test_comments $256;
39 | test_description=symget('desc');
40 | test_comments="&sysmacroname: Test result of "!!symget('iftrue');
41 | %if %eval(%unquote(&iftrue)) %then %do;
42 | test_result='PASS';
43 | %end;
44 | %else %do;
45 | test_result='FAIL';
46 | %end;
47 | run;
48 |
49 | %local ds ;
50 | %let ds=&syslast;
51 | proc append base=&outds data=&ds;
52 | run;
53 | proc sql;
54 | drop table &ds;
55 |
56 | %mend mp_assert;
--------------------------------------------------------------------------------
/base/mp_createwebservice.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file mp_createwebservice.sas
3 | @brief Create a web service in SAS 9, Viya or SASjs Server (legacy)
4 | @details This is actually a wrapper for mx_createwebservice.sas, remaining
5 | for legacy purposes. For new apps, use mx_createwebservice.sas.
6 |
7 |
8 | SAS Macros
9 | @li mx_createwebservice.sas
10 |
11 |
12 | **/
13 |
14 | %macro mp_createwebservice(path=HOME
15 | ,name=initService
16 | ,precode=
17 | ,code=ft15f001
18 | ,desc=This service was created by the mp_createwebservice macro
19 | ,replace=YES
20 | ,mdebug=0
21 | )/*/STORE SOURCE*/;
22 |
23 | %mx_createwebservice(path=&path
24 | ,name=&name
25 | ,precode=&precode
26 | ,code=&code
27 | ,desc=&desc
28 | ,replace=&replace
29 | ,mdebug=&mdebug
30 | )
31 |
32 | %mend mp_createwebservice;
33 |
--------------------------------------------------------------------------------
/base/mp_distinctfmtvalues.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Creates a dataset containing distinct _formatted_ values
4 | @details If no format is supplied, then the original value is used instead.
5 | There is also a dependency on other macros within the Macro Core library.
6 | Usage:
7 |
8 | %mp_distinctfmtvalues(libds=sashelp.class,var=age,outvar=age,outds=test)
9 |
10 | @param [in] libds= () input dataset
11 | @param [in] var= (0) variable to get distinct values for
12 | @param [out] outvar= (formatteed_value) variable to create.
13 | @param [out] outds= (work.mp_distinctfmtvalues) dataset to create.
14 | @param [in] varlen= (2000) length of variable to create
15 |
16 | @version 9.2
17 | @author Allan Bowe
18 |
19 | **/
20 |
21 | %macro mp_distinctfmtvalues(
22 | libds=
23 | ,var=
24 | ,outvar=formatted_value
25 | ,outds=work.mp_distinctfmtvalues
26 | ,varlen=2000
27 | )/*/STORE SOURCE*/;
28 |
29 | %local fmt vtype;
30 | %let fmt=%mf_getvarformat(&libds,&var);
31 | %let vtype=%mf_getvartype(&libds,&var);
32 |
33 | proc sql;
34 | create table &outds as
35 | select distinct
36 | %if &vtype=C & %trim(&fmt)=%str() %then %do;
37 | &var
38 | %end;
39 | %else %if &vtype=C %then %do;
40 | put(&var,&fmt)
41 | %end;
42 | %else %if %trim(&fmt)=%str() %then %do;
43 | put(&var,32.)
44 | %end;
45 | %else %do;
46 | put(&var,&fmt)
47 | %end;
48 | as &outvar length=&varlen
49 | from &libds;
50 | %mend mp_distinctfmtvalues;
--------------------------------------------------------------------------------
/base/mp_dropmembers.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Drops tables / views (if they exist) without warnings in the log
4 | @details Useful for dropping tables when you're not sure they exist, or if
5 | you are not sure whether they are a dataset or view. Also efficient for
6 | dropping multiple tables / views.
7 |
8 | Example usage:
9 |
10 | proc sql;
11 | create table data1 as select * from sashelp.class;
12 | create view view2 as select * from sashelp.class;
13 | %mp_dropmembers(data1 view2, libref=WORK)
14 |
15 |
16 | SAS Macros
17 | @li mf_isblank.sas
18 |
19 |
20 | @param [in] list space separated list of datasets / views, WITHOUT libref
21 | @param [in] libref= (WORK) Note - you can only drop from one library at a time
22 | @param [in] iftrue= (1=1) Conditionally drop tables, eg if &debug=N
23 |
24 | @version 9.2
25 | @author Allan Bowe
26 |
27 | **/
28 |
29 | %macro mp_dropmembers(
30 | list /* space separated list of datasets / views */
31 | ,libref=WORK /* can only drop from a single library at a time */
32 | ,iftrue=%str(1=1)
33 | )/*/STORE SOURCE*/;
34 |
35 | %if not(%eval(%unquote(&iftrue))) %then %return;
36 |
37 | %if %mf_isblank(&list) %then %do;
38 | %put NOTE: nothing to drop!;
39 | %return;
40 | %end;
41 |
42 | proc datasets lib=&libref nolist;
43 | delete &list;
44 | delete &list /mtype=view;
45 | run;
46 | %mend mp_dropmembers;
--------------------------------------------------------------------------------
/base/mp_ds2ddl.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Fetches DDL for a specific table
4 | @details Uses mp_getddl under the hood
5 |
6 | @param [in] libds library.dataset to create ddl for
7 | @param [in] fref= (getddl) the fileref to which to _append_ the DDL. If it
8 | does not exist, it will be created.
9 | @param [in] flavour= (SAS) The type of DDL to create. Options:
10 | @li SAS
11 | @li TSQL
12 |
13 | @param [in]showlog= (NO) Set to YES to show the DDL in the log
14 | @param [in] schema= () Choose a preferred schema name (default is to use
15 | actual schema, else libref)
16 | @param [in] applydttm= (NO) For non SAS DDL, choose if columns are created with
17 | native datetime2 format or regular decimal type
18 |
19 | SAS Macros
20 | @li mp_getddl.sas
21 |
22 | **/
23 |
24 | %macro mp_ds2ddl(libds,fref=getddl,flavour=SAS,showlog=YES,schema=
25 | ,applydttm=NO
26 | )/*/STORE SOURCE*/;
27 |
28 | %local libref;
29 | %let libds=%upcase(&libds);
30 | %let libref=%scan(&libds,1,.);
31 | %if &libref=&libds %then %let libds=WORK.&libds;
32 |
33 | %mp_getddl(%scan(&libds,1,.)
34 | ,%scan(&libds,2,.)
35 | ,fref=&fref
36 | ,flavour=SAS
37 | ,showlog=&showlog
38 | ,schema=&schema
39 | ,applydttm=&applydttm
40 | )
41 |
42 | %mend mp_ds2ddl;
--------------------------------------------------------------------------------
/base/mp_gitadd.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Stages files in a GIT repo
4 | @details Uses the output dataset from mp_gitstatus.sas to determine the files
5 | that should be staged.
6 |
7 | If `STAGED ne "TRUE"` then the file is staged.
8 |
9 | Usage:
10 |
11 | %let dir=%sysfunc(pathname(work))/core;
12 | %let repo=https://github.com/sasjs/core;
13 | %put source clone rc=%sysfunc(GITFN_CLONE(&repo,&dir));
14 | %mf_writefile(&dir/somefile.txt,l1=some content)
15 | %mf_deletefile(&dir/package.json)
16 | %mp_gitstatus(&dir,outds=work.gitstatus)
17 |
18 | %mp_gitadd(&dir,inds=work.gitstatus)
19 |
20 | @param [in] gitdir The directory containing the GIT repository
21 | @param [in] inds= (work.mp_gitadd) The input dataset with the list of files
22 | to stage. Will accept the output from mp_gitstatus(), else just use a table
23 | with the following columns:
24 | @li path $1024 - relative path to the file in the repo
25 | @li staged $32 - whether the file is staged (TRUE or FALSE)
26 | @li status $64 - either new, deleted, or modified
27 |
28 | @param [in] mdebug= (0) Set to 1 to enable DEBUG messages
29 |
30 | Related Files
31 | @li mp_gitadd.test.sas
32 | @li mp_gitstatus.sas
33 |
34 | **/
35 |
36 | %macro mp_gitadd(gitdir,inds=work.mp_gitadd,mdebug=0);
37 |
38 | data _null_;
39 | set &inds;
40 | if STAGED ne "TRUE";
41 | rc=git_index_add("&gitdir",cats(path),status);
42 | if rc ne 0 or &mdebug=1 then put rc=;
43 | run;
44 |
45 | %mend mp_gitadd;
46 |
--------------------------------------------------------------------------------
/base/mp_perflog.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Logs a message in a dataset every time it is invoked
4 | @details If the dataset does not exist, it is created.
5 | Usage:
6 |
7 | %mp_perflog(started)
8 | %mp_perflog()
9 | %mp_perflog(startanew,libds=work.newdataset)
10 | %mp_perflog(finished,libds=work.newdataset)
11 | %mp_perflog(finished)
12 |
13 |
14 | @param [in] label Provide label to go into the control dataset
15 | @param [in] libds= (work.mp_perflog) Provide a dataset in which to store
16 | performance stats. Default name is work.mp_perflog
;
17 |
18 | @version 9.2
19 | @author Allan Bowe
20 | @source https://github.com/sasjs/core
21 |
22 | **/
23 |
24 | %macro mp_perflog(label,libds=work.mp_perflog
25 | )/*/STORE SOURCE*/;
26 |
27 | %if not (%mf_existds(&libds)) %then %do;
28 | data &libds;
29 | length sysjobid $10 label $256 dttm 8.;
30 | format dttm datetime19.3;
31 | call missing(of _all_);
32 | stop;
33 | run;
34 | %end;
35 |
36 | proc sql;
37 | insert into &libds
38 | set sysjobid="&sysjobid"
39 | ,label=symget('label')
40 | ,dttm=%sysfunc(datetime());
41 | quit;
42 |
43 | %mend mp_perflog;
--------------------------------------------------------------------------------
/base/mp_reseterror.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Reset when an err condition occurs
4 | @details When building apps, sometimes an operation must be attempted that
5 | can cause an err condition. There is no try catch in SAS! So the err state
6 | must be caught and reset.
7 |
8 | This macro attempts to do that reset.
9 |
10 | @version 9.2
11 | @author Allan Bowe
12 |
13 | **/
14 |
15 | %macro mp_reseterror(
16 | )/*/STORE SOURCE*/;
17 |
18 | options obs=max replace nosyntaxcheck;
19 | %let syscc=0;
20 |
21 | %if "&sysprocessmode " = "SAS Stored Process Server " %then %do;
22 | data _null_;
23 | rc=stpsrvset('program error', 0);
24 | run;
25 | %end;
26 |
27 | %mend mp_reseterror;
--------------------------------------------------------------------------------
/base/mp_resetoption.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Reset an option to original value
4 | @details Inspired by the SAS Jedi -
5 | https://blogs.sas.com/content/sastraining/2012/08/14/jedi-sas-tricks-reset-sas-system-options
6 |
7 | Called as follows:
8 |
9 | options obs=30 ps=max;
10 | %mp_resetoption(OBS)
11 | %mp_resetoption(PS)
12 |
13 |
14 | @param [in] option the option to reset
15 |
16 | @version 9.2
17 | @author Allan Bowe
18 |
19 | **/
20 |
21 | %macro mp_resetoption(option /* the option to reset */
22 | )/*/STORE SOURCE*/;
23 |
24 | %if "%substr(&sysver,1,1)" ne "4" and "%substr(&sysver,1,1)" ne "5" %then %do;
25 | data _null_;
26 | length code $1500;
27 | startup=getoption("&option",'startupvalue');
28 | current=getoption("&option");
29 | if startup ne current then do;
30 | code =cat('OPTIONS ',getoption("&option",'keyword','startupvalue'),';');
31 | putlog "NOTE: Resetting system option: " code ;
32 | call execute(code );
33 | end;
34 | run;
35 | %end;
36 | %else %do;
37 | %put &sysmacroname: reset option feature unavailable on &sysvlong;
38 | %end;
39 | %mend mp_resetoption;
--------------------------------------------------------------------------------
/base/mp_runddl.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file mp_runddl.sas
3 | @brief An opinionated way to execute DDL files in SAS.
4 | @details When delivering projects there should be seperation between the DDL
5 | used to generate the tables and the sample data used to populate them.
6 |
7 | This macro expects certain folder structure - eg:
8 |
9 | rootlib
10 | |-- LIBREF1
11 | | |__ mytable.ddl
12 | | |__ someothertable.ddl
13 | |-- LIBREF2
14 | | |__ table1.ddl
15 | | |__ table2.ddl
16 | |-- LIBREF3
17 | |__ table3.ddl
18 | |__ table4.ddl
19 |
20 | Only files with the .ddl suffix are executed. The parent folder name is used
21 | as the libref.
22 | Files should NOT contain the `proc sql` statement - this is to prevent
23 | statements being executed if there is an err condition.
24 |
25 | Usage:
26 |
27 | %mp_runddl(/some/rootlib) * execute all libs ;
28 |
29 | %mp_runddl(/some/rootlib, inc=LIBREF1 LIBREF2) * include only these libs;
30 |
31 | %mp_runddl(/some/rootlib, exc=LIBREF3) * same as above ;
32 |
33 |
34 | @param [in] path location of the DDL folder structure
35 | @param [in] inc= list of librefs to include
36 | @param [in] exc= list of librefs to exclude (takes precedence over inc=)
37 |
38 | @version 9.3
39 | @author Allan Bowe
40 | @source https://github.com/sasjs/core
41 |
42 | **/
43 |
44 | %macro mp_runddl(path, inc=, exc=
45 | )/*/STORE SOURCE*/;
46 |
47 |
48 |
49 | %mend mp_runddl;
--------------------------------------------------------------------------------
/base/mp_setkeyvalue.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Logs a key value pair a control dataset
4 | @details If the dataset does not exist, it is created. Usage:
5 |
6 | %mp_setkeyvalue(someindex,22,type=N)
7 | %mp_setkeyvalue(somenewindex,somevalue)
8 |
9 | SAS Macros
10 | @li mf_existds.sas
11 |
12 | Related Macros
13 | @li mf_getvalue.sas
14 |
15 | @param [in] key Provide a key on which to perform the lookup
16 | @param [in] value Provide a value
17 | @param [in] type= either C or N will populate valc and valn respectively.
18 | C is default.
19 | @param [out] libds= define the target table to hold the parameters
20 |
21 | @version 9.2
22 | @author Allan Bowe
23 | @source https://github.com/sasjs/core
24 |
25 | **/
26 |
27 | %macro mp_setkeyvalue(key,value,type=C,libds=work.mp_setkeyvalue
28 | )/*/STORE SOURCE*/;
29 |
30 | %if not (%mf_existds(&libds)) %then %do;
31 | data &libds (index=(key/unique));
32 | length key $64 valc $2048 valn 8 type $1;
33 | call missing(of _all_);
34 | stop;
35 | run;
36 | %end;
37 |
38 | proc sql;
39 | delete from &libds
40 | where key=symget('key');
41 | insert into &libds
42 | set key=symget('key')
43 | %if &type=C %then %do;
44 | ,valc=symget('value')
45 | ,type='C'
46 | %end;
47 | %else %do;
48 | ,valn=symgetn('value')
49 | ,type='N'
50 | %end;
51 | ;
52 |
53 | quit;
54 |
55 | %mend mp_setkeyvalue;
--------------------------------------------------------------------------------
/base/mp_testservice.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief To be deprecated. Will execute a SASjs web service on SAS 9 or Viya
4 | @details Use the mx_testservice.sas macro instead (documentation can be
5 | found there)
6 |
7 | SAS Macros
8 | @li mx_testservice.sas
9 |
10 | @version 9.4
11 | @author Allan Bowe
12 |
13 | **/
14 |
15 | %macro mp_testservice(program,
16 | inputfiles=0,
17 | inputdatasets=0,
18 | inputparams=0,
19 | debug=log,
20 | mdebug=0,
21 | outlib=0,
22 | outref=0,
23 | viyaresult=WEBOUT_JSON,
24 | viyacontext=SAS Job Execution compute context
25 | )/*/STORE SOURCE*/;
26 |
27 | %mx_testservice(&program,
28 | inputfiles=&inputfiles,
29 | inputdatasets=&inputdatasets,
30 | inputparams=&inputparams,
31 | debug=&debug,
32 | mdebug=&mdebug,
33 | outlib=&outlib,
34 | outref=&outref,
35 | viyaresult=&viyaresult,
36 | viyacontext=&viyacontext
37 | )
38 |
39 | %mend mp_testservice;
40 |
--------------------------------------------------------------------------------
/base/mp_testwritespeedlibrary.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file mp_testwritespeedlibrary.sas
3 | @brief Tests the write speed of a new table in a SAS library
4 | @details Will create a new table of a certain size in an
5 | existing SAS library. The table will have one column,
6 | and will be subsequently deleted.
7 |
8 | %mp_testwritespeedlibrary(
9 | lib=work
10 | ,size=0.5
11 | ,outds=work.results
12 | )
13 |
14 | @param [in] lib= (WORK) The library in which to create the table
15 | @param [in] size= (0.1) The size in GB of the table to create
16 | @param [out] outds= (WORK.RESULTS) The output dataset to be created.
17 |
18 | SAS Macros
19 | @li mf_getuniquename.sas
20 | @li mf_existds.sas
21 |
22 | @version 9.4
23 | @author Allan Bowe
24 |
25 | **/
26 |
27 | %macro mp_testwritespeedlibrary(lib=WORK
28 | ,outds=work.results
29 | ,size=0.1
30 | )/*/STORE SOURCE*/;
31 | %local ds start;
32 |
33 | /* find an unused, unique name for the new table */
34 | %let ds=%mf_getuniquename();
35 | %do %until(%mf_existds(&lib..&ds)=0);
36 | %let ds=%mf_getuniquename();
37 | %end;
38 |
39 | %let start=%sysfunc(datetime());
40 |
41 | data &lib..&ds(compress=no keep=x);
42 | header=128*1024;
43 | size=(1073741824/8 * &size) - header;
44 | do x=1 to size;
45 | output;
46 | end;
47 | run;
48 |
49 | proc sql;
50 | drop table &lib..&ds;
51 |
52 | data &outds;
53 | lib="&lib";
54 | start_dttm=put(&start,datetime19.);
55 | end_dttm=put(datetime(),datetime19.);
56 | duration_seconds=end_dttm-start_dttm;
57 | run;
58 |
59 | %mend mp_testwritespeedlibrary;
--------------------------------------------------------------------------------
/base/mp_wait4file.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Wait until a file arrives before continuing execution
4 | @details Loops with a `sleep()` command until a file arrives or the max wait
5 | period expires.
6 |
7 | Example: Wait 3 minutes OR for /tmp/flag.txt to appear
8 |
9 | %mp_wait4file(/tmp/flag.txt , maxwait=60*3)
10 |
11 | @param [in] file The file to wait for. Must be provided.
12 | @param [in] maxwait= (0) Number of seconds to wait. If set to zero, will
13 | loop indefinitely (to a maximum of 46 days, per SAS [documentation](
14 | https://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a001418809.htm
15 | )). Otherwise, execution will proceed upon sleep expiry.
16 | @param [in] interval= (1) The wait period between sleeps, in seconds
17 |
18 |
19 | **/
20 |
21 | %macro mp_wait4file(file, maxwait=0, interval=1);
22 |
23 | %if %str(&file)=%str() %then %do;
24 | %put %str(ERR)OR: file not provided;
25 | %end;
26 |
27 | data _null_;
28 | maxwait=&maxwait;
29 | if maxwait=0 then maxwait=60*60*24*46;
30 | do until (fileexist("&file") or slept>maxwait );
31 | slept=sum(slept,sleep(&interval,1));
32 | end;
33 | run;
34 |
35 | %mend mp_wait4file;
--------------------------------------------------------------------------------
/ddl/mddl_dc_difftable.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Difftable DDL
4 | @details Used to store changes to tables. Used by mp_storediffs.sas
5 | and mp_stackdiffs.sas
6 |
7 | **/
8 |
9 |
10 | %macro mddl_dc_difftable(libds=WORK.DIFFTABLE);
11 |
12 | proc sql;
13 | create table &libds(
14 | load_ref char(36) label='unique load reference',
15 | processed_dttm num format=E8601DT26.6 label='Processed at timestamp',
16 | libref char(8) label='Library Reference (8 chars)',
17 | dsn char(32) label='Dataset Name (32 chars)',
18 | key_hash char(32) label=
19 | 'MD5 Hash of primary key values (pipe seperated)',
20 | move_type char(1) label='Either (A)ppended, (D)eleted or (M)odified',
21 | is_pk num label='Is Primary Key Field? (1/0)',
22 | is_diff num label=
23 | 'Did value change? (1/0/-1). Always -1 for appends and deletes.',
24 | tgtvar_type char(1) label='Either (C)haracter or (N)umeric',
25 | tgtvar_nm char(32) label='Target variable name (32 chars)',
26 | oldval_num num format=best32. label='Old (numeric) value',
27 | newval_num num format=best32. label='New (numeric) value',
28 | oldval_char char(32765) label='Old (character) value',
29 | newval_char char(32765) label='New (character) value'
30 | );
31 |
32 | %local lib;
33 | %let libds=%upcase(&libds);
34 | %if %index(&libds,.)=0 %then %let lib=WORK;
35 | %else %let lib=%scan(&libds,1,.);
36 |
37 | proc datasets lib=&lib noprint;
38 | modify %scan(&libds,-1,.);
39 | index create
40 | pk_mpe_audit=(load_ref libref dsn key_hash tgtvar_nm)
41 | /nomiss unique;
42 | quit;
43 |
44 | %mend mddl_dc_difftable;
--------------------------------------------------------------------------------
/ddl/mddl_dc_filterdetail.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Filtertable DDL
4 | @details For storing detailed filter values. Used by
5 | mp_filterstore.sas.
6 |
7 | **/
8 |
9 |
10 | %macro mddl_dc_filterdetail(libds=WORK.FILTER_DETAIL);
11 |
12 | %local nn lib;
13 | %if "%substr(&sysver,1,1)" ne "4" and "%substr(&sysver,1,1)" ne "5" %then %do;
14 | %let nn=not null;
15 | %end;
16 | %else %let nn=;
17 |
18 | proc sql;
19 | create table &libds(
20 | filter_hash char(32) &nn,
21 | filter_line num &nn,
22 | group_logic char(3) &nn,
23 | subgroup_logic char(3) &nn,
24 | subgroup_id num &nn,
25 | variable_nm varchar(32) &nn,
26 | operator_nm varchar(12) &nn,
27 | raw_value varchar(4000) &nn,
28 | processed_dttm num &nn format=E8601DT26.6
29 | );
30 |
31 | %let libds=%upcase(&libds);
32 | %if %index(&libds,.)=0 %then %let lib=WORK;
33 | %else %let lib=%scan(&libds,1,.);
34 |
35 | proc datasets lib=&lib noprint;
36 | modify %scan(&libds,-1,.);
37 | index create pk_mpe_filterdetail=(filter_hash filter_line)/nomiss unique;
38 | quit;
39 |
40 | %mend mddl_dc_filterdetail;
--------------------------------------------------------------------------------
/ddl/mddl_dc_filtersummary.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Filtersummary DDL
4 | @details For storing summary filter values. Used by
5 | mp_filterstore.sas.
6 |
7 | **/
8 |
9 |
10 | %macro mddl_dc_filtersummary(libds=WORK.FILTER_SUMMARY);
11 |
12 | %local nn lib;
13 | %if "%substr(&sysver,1,1)" ne "4" and "%substr(&sysver,1,1)" ne "5" %then %do;
14 | %let nn=not null;
15 | %end;
16 | %else %let nn=;
17 |
18 | proc sql;
19 | create table &libds(
20 | filter_rk num &nn,
21 | filter_hash char(32) &nn,
22 | filter_table char(41) &nn,
23 | processed_dttm num &nn format=E8601DT26.6
24 | );
25 |
26 | %let libds=%upcase(&libds);
27 | %if %index(&libds,.)=0 %then %let lib=WORK;
28 | %else %let lib=%scan(&libds,1,.);
29 |
30 | proc datasets lib=&lib noprint;
31 | modify %scan(&libds,-1,.);
32 | index create filter_rk /nomiss unique;
33 | quit;
34 |
35 | %mend mddl_dc_filtersummary;
--------------------------------------------------------------------------------
/ddl/mddl_dc_locktable.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Locktable DDL
4 | @details For "locking" tables prior to multipass loads. Used by
5 | mp_lockanytable.sas
6 |
7 | **/
8 |
9 |
10 | %macro mddl_dc_locktable(libds=WORK.LOCKTABLE);
11 |
12 | %local nn lib;
13 | %if "%substr(&sysver,1,1)" ne "4" and "%substr(&sysver,1,1)" ne "5" %then %do;
14 | %let nn=not null;
15 | %end;
16 | %else %let nn=;
17 |
18 | proc sql;
19 | create table &libds(
20 | lock_lib char(8),
21 | lock_ds char(32),
22 | lock_status_cd char(10) &nn,
23 | lock_user_nm char(100) &nn ,
24 | lock_ref char(200),
25 | lock_pid char(10),
26 | lock_start_dttm num format=E8601DT26.6,
27 | lock_end_dttm num format=E8601DT26.6
28 | );
29 |
30 | %let libds=%upcase(&libds);
31 | %if %index(&libds,.)=0 %then %let lib=WORK;
32 | %else %let lib=%scan(&libds,1,.);
33 |
34 | proc datasets lib=&lib noprint;
35 | modify %scan(&libds,-1,.);
36 | index create
37 | pk_mp_lockanytable=(lock_lib lock_ds)
38 | /nomiss unique;
39 | quit;
40 |
41 | %mend mddl_dc_locktable;
--------------------------------------------------------------------------------
/ddl/mddl_dc_maxkeytable.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Maxkeytable DDL
4 | @details For storing the maximum retained key information. Used
5 | by mp_retainedkey.sas
6 |
7 | **/
8 |
9 |
10 | %macro mddl_dc_maxkeytable(libds=WORK.MAXKEYTABLE);
11 |
12 | proc sql;
13 | create table &libds(
14 | keytable varchar(41) label='Base table in libref.dataset format',
15 | keycolumn char(32) format=$32.
16 | label='The Retained key field containing the key values.',
17 | max_key num label=
18 | 'Integer representing current max RK or SK value in the KEYTABLE',
19 | processed_dttm num format=E8601DT26.6
20 | label='Datetime this value was last updated'
21 | );
22 |
23 | %local lib;
24 | %let libds=%upcase(&libds);
25 | %if %index(&libds,.)=0 %then %let lib=WORK;
26 | %else %let lib=%scan(&libds,1,.);
27 |
28 | proc datasets lib=&lib noprint;
29 | modify %scan(&libds,-1,.);
30 | index create keytable /nomiss unique;
31 | quit;
32 |
33 | %mend mddl_dc_maxkeytable;
--------------------------------------------------------------------------------
/fcmp/mcf_init.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Sets up the mcf_xx functions
4 | @details
5 | There is no (efficient) way to determine if an mcf_xx macro has already been
6 | invoked. So, we make use of a global macro variable list to keep track.
7 |
8 | Usage:
9 |
10 | %mcf_init(MCF_LENGTH)
11 |
12 | Returns:
13 |
14 | > 1 (if already initialised) else 0
15 |
16 | @param [in] func The function to be initialised
17 |
18 | Related Macros
19 | @li mcf_init.test.sas
20 |
21 | **/
22 |
23 | %macro mcf_init(func
24 | )/*/STORE SOURCE*/;
25 |
26 | %if not (%symexist(SASJS_PREFIX)) %then %do;
27 | %global SASJS_PREFIX;
28 | %let SASJS_PREFIX=SASJS;
29 | %end;
30 |
31 | %let func=%upcase(&func);
32 |
33 | /* the / character is just a seperator */
34 | %global &sasjs_prefix._FUNCTIONS;
35 | %if %index(&&&sasjs_prefix._FUNCTIONS,&func/)>0 %then %do;
36 | 1
37 | %return;
38 | %end;
39 | %else %do;
40 | %let &sasjs_prefix._FUNCTIONS=&&&sasjs_prefix._FUNCTIONS &func/;
41 | 0
42 | %end;
43 |
44 | %mend mcf_init;
45 |
--------------------------------------------------------------------------------
/lua/gsubfile.lua:
--------------------------------------------------------------------------------
1 | local fpath, outpath, file, fcontent
2 |
3 | -- configure in / out paths
4 | fpath = sas.symget("file")
5 | outpath = sas.symget("outfile")
6 | if ( outpath == 0 )
7 | then
8 | outpath=fpath
9 | end
10 |
11 | -- open file and perform the substitution
12 | file = io.open(fpath,"r")
13 | fcontent = file:read("*all")
14 | file:close()
15 | fcontent = string.gsub(
16 | fcontent,
17 | sas.symget(sas.symget("patternvar")),
18 | sas.symget(sas.symget("replacevar"))
19 | )
20 |
21 | -- write the file back out
22 | file = io.open(outpath, "w+")
23 | io.output(file)
24 | io.write(fcontent)
25 | io.close(file)
--------------------------------------------------------------------------------
/lua/ml_gsubfile.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file ml_gsubfile.sas
3 | @brief Compiles the gsubfile.lua lua file
4 | @details Writes gsubfile.lua to the work directory
5 | and then includes it.
6 | Usage:
7 |
8 | %ml_gsubfile()
9 |
10 | **/
11 |
12 | %macro ml_gsubfile();
13 | data _null_;
14 | file "%sysfunc(pathname(work))/ml_gsubfile.lua";
15 | put 'local fpath, outpath, file, fcontent ';
16 | put ' ';
17 | put '-- configure in / out paths ';
18 | put 'fpath = sas.symget("file") ';
19 | put 'outpath = sas.symget("outfile") ';
20 | put 'if ( outpath == 0 ) ';
21 | put 'then ';
22 | put ' outpath=fpath ';
23 | put 'end ';
24 | put ' ';
25 | put '-- open file and perform the substitution ';
26 | put 'file = io.open(fpath,"r") ';
27 | put 'fcontent = file:read("*all") ';
28 | put 'file:close() ';
29 | put 'fcontent = string.gsub( ';
30 | put ' fcontent, ';
31 | put ' sas.symget(sas.symget("patternvar")), ';
32 | put ' sas.symget(sas.symget("replacevar")) ';
33 | put ') ';
34 | put ' ';
35 | put '-- write the file back out ';
36 | put 'file = io.open(outpath, "w+") ';
37 | put 'io.output(file) ';
38 | put 'io.write(fcontent) ';
39 | put 'io.close(file) ';
40 | run;
41 |
42 | /* ensure big enough lrecl to avoid lua compilation issues */
43 | %local optval;
44 | %let optval=%sysfunc(getoption(lrecl));
45 | options lrecl=1024;
46 |
47 | /* execute the lua code by using a .lua extension */
48 | %inc "%sysfunc(pathname(work))/ml_gsubfile.lua" /source2;
49 |
50 | options lrecl=&optval;
51 |
52 | %mend ml_gsubfile;
53 |
--------------------------------------------------------------------------------
/meta/mm_getcols.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Creates a dataset with all metadata columns for a particular table
4 | @details
5 |
6 | usage:
7 |
8 | %mm_getcols(tableuri=A5X8AHW1.B40001S5)
9 |
10 | @param [out] outds the dataset to create that contains the list of columns
11 | @param [in] uri the uri of the table for which to return columns
12 |
13 | @returns outds dataset containing all columns, specifically:
14 | - colname
15 | - coluri
16 | - coldesc
17 |
18 | @version 9.2
19 | @author Allan Bowe
20 |
21 | **/
22 |
23 | %macro mm_getcols(
24 | tableuri=
25 | ,outds=work.mm_getcols
26 | )/*/STORE SOURCE*/;
27 |
28 | data &outds;
29 | keep col: SAS:;
30 | length assoc uri coluri colname coldesc SASColumnType SASFormat SASInformat
31 | SASPrecision SASColumnLength $256;
32 | call missing (of _all_);
33 | uri=symget('tableuri');
34 | n=1;
35 | do while (metadata_getnasn(uri,'Columns',n,coluri)>0);
36 | rc3=metadata_getattr(coluri,"Name",colname);
37 | rc3=metadata_getattr(coluri,"Desc",coldesc);
38 | rc4=metadata_getattr(coluri,"SASColumnType",SASColumnType);
39 | rc5=metadata_getattr(coluri,"SASFormat",SASFormat);
40 | rc6=metadata_getattr(coluri,"SASInformat",SASInformat);
41 | rc7=metadata_getattr(coluri,"SASPrecision",SASPrecision);
42 | rc8=metadata_getattr(coluri,"SASColumnLength",SASColumnLength);
43 | output;
44 | call missing(colname,coldesc,SASColumnType,SASFormat,SASInformat
45 | ,SASPrecision,SASColumnLength);
46 | n+1;
47 | end;
48 | run;
49 | proc sort;
50 | by colname;
51 | run;
52 |
53 | %mend mm_getcols;
--------------------------------------------------------------------------------
/metax/mmx_createmetafolder.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Creates a metadata folder
4 | @details Creates a metadata folder using the batch tools
5 |
6 | Usage:
7 |
8 | %mmx_createmetafolder(loc=/some/meta/folder,user=sasdemo,pass=mars345)
9 |
10 | SAS Macros
11 | @li mf_loc.sas
12 | @li mp_abort.sas
13 |
14 | @param [in] loc= the metadata folder to delete
15 | @param [in] user= username
16 | @param [in] pass= password
17 |
18 | @version 9.4
19 | @author Allan Bowe
20 |
21 | **/
22 |
23 | %macro mmx_createmetafolder(loc=,user=,pass=);
24 |
25 | %local host port path connx_string msg;
26 | %let host=%sysfunc(getoption(metaserver));
27 | %let port=%sysfunc(getoption(metaport));
28 | %let path=%mf_loc(POF)/tools;
29 |
30 | %let connx_string= -host &host -port &port -user '&user' -password '&pass';
31 | /* remove directory */
32 | data _null_;
33 | infile " &path/sas-make-folder &connx_string ""&loc"" -makeFullPath 2>&1"
34 | pipe lrecl=10000;
35 | input;
36 | putlog _infile_;
37 | run;
38 |
39 | data _null_; /* check tree exists */
40 | length type uri $256;
41 | rc=metadata_pathobj("","&loc","Folder",type,uri);
42 | call symputx('foldertype',type,'l');
43 | run;
44 | %let msg=Location (&loc) was not created!!;
45 | %mp_abort(iftrue= (&foldertype ne Tree)
46 | ,mac=&_program..sas
47 | ,msg=%superq(msg)
48 | )
49 |
50 | %mend mmx_createmetafolder;
51 |
--------------------------------------------------------------------------------
/metax/mmx_deletemetafolder.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Deletes a metadata folder
4 | @details Deletes a metadata folder (and contents) using the batch tools, as
5 | documented here:
6 | https://documentation.sas.com/?docsetId=bisag&docsetTarget=p0zqp8fmgs4o0kn1tt7j8ho829fv.htm&docsetVersion=9.4&locale=en
7 |
8 | Usage:
9 |
10 | %mmx_deletemetafolder(loc=/some/meta/folder,user=sasdemo,pass=mars345)
11 |
12 | SAS Macros
13 | @li mf_loc.sas
14 |
15 | @param [in] loc= the metadata folder to delete
16 | @param [in] user= username
17 | @param [in] pass= password
18 |
19 | @version 9.4
20 | @author Allan Bowe
21 |
22 | **/
23 |
24 | %macro mmx_deletemetafolder(loc=,user=,pass=);
25 |
26 | %local host port path connx_string;
27 | %let host=%sysfunc(getoption(metaserver));
28 | %let port=%sysfunc(getoption(metaport));
29 | %let path=%mf_loc(POF)/tools;
30 |
31 | %let connx_string= -host &host -port &port -user '&user' -password '&pass';
32 | /* remove directory */
33 | data _null_;
34 | infile " &path/sas-delete-objects &connx_string ""&loc"" -deleteContents 2>&1"
35 | pipe lrecl=10000;
36 | input;
37 | putlog _infile_;
38 | run;
39 |
40 | %mend mmx_deletemetafolder;
41 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@sasjs/core",
3 | "lockfileVersion": 3,
4 | "requires": true,
5 | "packages": {
6 | "": {
7 | "name": "@sasjs/core",
8 | "license": "MIT"
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@sasjs/core",
3 | "description": "Macros for SAS Application Developers",
4 | "license": "MIT",
5 | "keywords": [
6 | "SAS",
7 | "Viya",
8 | "SASjs"
9 | ],
10 | "author": "Allan Bowe",
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/sasjs/core.git"
14 | },
15 | "release": {
16 | "branches": [
17 | "main"
18 | ]
19 | },
20 | "publishConfig": {
21 | "access": "public"
22 | },
23 | "bugs": {
24 | "url": "https://github.com/sasjs/core/issues"
25 | },
26 | "homepage": "https://core.sasjs.io",
27 | "main": "index.js",
28 | "scripts": {
29 | "build": "npx @sasjs/cli cbd -t server",
30 | "docs": "npx @sasjs/cli doc -t docsonly && ./sasjs/utils/build.sh",
31 | "test": "npx @sasjs/cli test -t server",
32 | "lint": "npx @sasjs/cli lint",
33 | "prepare": "git rev-parse --git-dir && git config core.hooksPath ./.git-hooks || true"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/sasjs/doxy/Doxyfile:
--------------------------------------------------------------------------------
1 | ALPHABETICAL_INDEX = NO
2 | DISABLE_INDEX = NO
3 | ENABLE_PREPROCESSING = NO
4 | EXTENSION_MAPPING = sas=Java ddl=Java
5 | EXTRACT_LOCAL_CLASSES = NO
6 | FILE_PATTERNS = *.sas \
7 | *.ddl \
8 | *.dox
9 | GENERATE_LATEX = NO
10 | GENERATE_TREEVIEW = YES
11 | HAVE_DOT = YES
12 | HIDE_FRIEND_COMPOUNDS = YES
13 | HIDE_IN_BODY_DOCS = YES
14 | HIDE_SCOPE_NAMES = YES
15 | HIDE_UNDOC_CLASSES = YES
16 | HIDE_UNDOC_MEMBERS = YES
17 | HTML_OUTPUT = $(DOXY_HTML_OUTPUT)
18 | HTML_HEADER = $(HTML_HEADER)
19 | HTML_EXTRA_FILES = $(HTML_EXTRA_FILES)
20 | HTML_FOOTER = $(HTML_FOOTER)
21 | HTML_EXTRA_STYLESHEET = $(HTML_EXTRA_STYLESHEET)
22 | INHERIT_DOCS = NO
23 | INLINE_INFO = NO
24 | INPUT = $(DOXY_INPUT)
25 | INPUT += main.dox
26 | LAYOUT_FILE = $(LAYOUT_FILE)
27 | USE_MDFILE_AS_MAINPAGE = README.md
28 | MAX_INITIALIZER_LINES = 0
29 | PROJECT_NAME = $(PROJECT_NAME)
30 | PROJECT_LOGO = $(PROJECT_LOGO)
31 | PROJECT_BRIEF = $(PROJECT_BRIEF)
32 | RECURSIVE = YES
33 | REPEAT_BRIEF = NO
34 | SHOW_NAMESPACES = NO
35 | SHOW_USED_FILES = NO
36 | SOURCE_BROWSER = YES
37 | SOURCE_TOOLTIPS = NO
38 | STRICT_PROTO_MATCHING = YES
39 | STRIP_CODE_COMMENTS = NO
40 | SUBGROUPING = NO
41 | TAB_SIZE = 2
42 | VERBATIM_HEADERS = NO
--------------------------------------------------------------------------------
/sasjs/doxy/Macro_core_website_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sasjs/core/6dbfd32dbaa57b476948202d9b6ae3cc51559fa1/sasjs/doxy/Macro_core_website_1.png
--------------------------------------------------------------------------------
/sasjs/doxy/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sasjs/core/6dbfd32dbaa57b476948202d9b6ae3cc51559fa1/sasjs/doxy/favicon.ico
--------------------------------------------------------------------------------
/sasjs/doxy/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sasjs/core/6dbfd32dbaa57b476948202d9b6ae3cc51559fa1/sasjs/doxy/logo.png
--------------------------------------------------------------------------------
/sasjs/doxy/new_footer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | $navpath
8 |
15 | -
16 | For more information visit the
17 | Macro Core library.
18 |
19 |
20 |
21 |
22 |
23 |
24 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/sasjs/doxy/new_stylesheet.css:
--------------------------------------------------------------------------------
1 | #projectlogo img
2 | {
3 | border: 0px none;
4 | max-height:70px
5 | }
--------------------------------------------------------------------------------
/sasjs/doxy/runningman.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sasjs/core/6dbfd32dbaa57b476948202d9b6ae3cc51559fa1/sasjs/doxy/runningman.jpg
--------------------------------------------------------------------------------
/sasjs/utils/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ####################################################################
3 | # PROJECT: SASjs Core Docs Build
4 | # To execute, use the npm command (npm run docs)
5 | # Target repo will have github action to create sitemap
6 | # https://github.com/marketplace/actions/generate-sitemap
7 | ####################################################################
8 |
9 | # refresh github pages site
10 | rm -rf sasjsbuild/docsite
11 | git clone git@github.com:sasjs/core.github.io.git sasjsbuild/docsite
12 | rm -rf sasjsbuild/docsite/*.html
13 | rm -rf sasjsbuild/docsite/*.js
14 | rm -rf sasjsbuild/docsite/*.png
15 | rm -rf sasjsbuild/docsite/*.dot
16 | rm -rf sasjsbuild/docsite/*.css
17 | rm -rf sasjsbuild/docsite/*.svg
18 | rm -rf search
19 | cp -R sasjsbuild/docs/* sasjsbuild/docsite/
20 | cd sasjsbuild/docsite/
21 | git config user.name sasjs
22 | echo 'core.sasjs.io' > CNAME
23 | git add .
24 | git commit -m "build.sh build on $(date +%F:%H:%M:%S)"
25 | git push
26 |
27 | echo "check it out: https://sasjs.github.io/core.github.io/files.html"
28 |
--------------------------------------------------------------------------------
/server/mfs_httpheader.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Sets the http headers in the SASjs/server response
4 | @details For GET requests, SASjs server will use the file generated by this
5 | macro for setting the appropriate http headers in the response.
6 |
7 | It works by writing a file to the session directory, that is then ingested by
8 | the server.
9 |
10 | The location of this file is driven by the global variable
11 | `sasjs_stpsrv_header_loc` which is made available in the autoexec.
12 |
13 | Usage:
14 |
15 | %mfs_httpheader(Content-Type,application/csv)
16 |
17 | @param [in] header_name Name of the http header to set
18 | @param [in] header_value Value of the http header to set
19 |
20 | Related Macros
21 | @li mcf_stpsrv_header.sas
22 |
23 | @version 9.3
24 | @author Allan Bowe
25 |
26 | **/
27 |
28 | %macro mfs_httpheader(header_name
29 | ,header_value
30 | )/*/STORE SOURCE*/;
31 | %global sasjs_stpsrv_header_loc;
32 | %local fref fid i;
33 |
34 | %if %sysfunc(filename(fref,&sasjs_stpsrv_header_loc)) ne 0 %then %do;
35 | %put &=fref &=sasjs_stpsrv_header_loc;
36 | %put %str(ERR)OR: %sysfunc(sysmsg());
37 | %return;
38 | %end;
39 |
40 | %let fid=%sysfunc(fopen(&fref,A));
41 |
42 | %if &fid=0 %then %do;
43 | %put %str(ERR)OR: %sysfunc(sysmsg());
44 | %return;
45 | %end;
46 |
47 | %let rc=%sysfunc(fput(&fid,%str(&header_name): %str(&header_value)));
48 | %let rc=%sysfunc(fwrite(&fid));
49 |
50 | %let rc=%sysfunc(fclose(&fid));
51 | %let rc=%sysfunc(filename(&fref));
52 |
53 | %mend mfs_httpheader;
54 |
--------------------------------------------------------------------------------
/server/ms_deletefile.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Deletes a file from SASjs Drive
4 | @details Deletes a file from SASjs Drive, if it exists.
5 |
6 | Example:
7 |
8 | filename stpcode temp;
9 | data _null_;
10 | file stpcode;
11 | put '%put hello world;';
12 | run;
13 | %ms_createfile(/some/stored/program.sas, inref=stpcode)
14 |
15 | %ms_deletefile(/some/stored/program.sas)
16 |
17 | @param [in] driveloc The full path to the file in SASjs Drive
18 | @param [in] mdebug= (0) Set to 1 to enable DEBUG messages
19 |
20 | SAS Macros
21 | @li mf_getuniquefileref.sas
22 |
23 | **/
24 |
25 | %macro ms_deletefile(driveloc
26 | ,mdebug=0
27 | );
28 |
29 | %local headref;
30 | %let headref=%mf_getuniquefileref();
31 |
32 | data _null_;
33 | file &headref lrecl=1000;
34 | infile "&_sasjs_tokenfile" lrecl=1000;
35 | input;
36 | put _infile_;
37 | run;
38 |
39 | proc http method='DELETE' headerin=&headref
40 | url="&_sasjs_apiserverurl/SASjsApi/drive/file?_filePath=&driveloc";
41 | %if &mdebug=1 %then %do;
42 | debug level=2;
43 | %end;
44 | run;
45 |
46 | filename &headref clear;
47 |
48 | %mend ms_deletefile;
49 |
--------------------------------------------------------------------------------
/server/ms_getfile.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Gets a file from SASjs Drive
4 | @details Fetches a file on SASjs Drive and stores it in the output fileref.
5 |
6 | Example:
7 |
8 | %ms_getfile(/Public/app/dc/services/public/settings.sas, outref=myfile)
9 |
10 | @param [in] driveloc The full path to the file in SASjs Drive
11 | @param [out] outref= (msgetfil) The fileref to contain the file.
12 | @param [in] mdebug= (0) Set to 1 to enable DEBUG messages
13 |
14 | SAS Macros
15 | @li mf_getuniquefileref.sas
16 | @li mf_getuniquename.sas
17 |
18 | **/
19 |
20 | %macro ms_getfile(driveloc
21 | ,outref=msgetfil
22 | ,mdebug=0
23 | );
24 |
25 | /* use the recfm in a separate fileref to avoid issues with subsequent reads */
26 | %local binaryfref floc headref;
27 | %let binaryfref=%mf_getuniquefileref();
28 | %let headref=%mf_getuniquefileref();
29 | %let floc=%sysfunc(pathname(work))/%mf_getuniquename().txt;
30 | filename &outref "&floc" lrecl=32767;
31 | filename &binaryfref "&floc" recfm=n;
32 |
33 | data _null_;
34 | file &headref lrecl=1000;
35 | infile "&_sasjs_tokenfile" lrecl=1000;
36 | input;
37 | put _infile_;
38 | run;
39 |
40 | proc http method='GET' out=&binaryfref headerin=&headref
41 | url="&_sasjs_apiserverurl/SASjsApi/drive/file?_filePath=&driveloc";
42 | %if &mdebug=1 %then %do;
43 | debug level=2;
44 | %end;
45 | run;
46 |
47 | filename &binaryfref clear;
48 | filename &headref clear;
49 |
50 | %mend ms_getfile;
--------------------------------------------------------------------------------
/tests/base/mcf_getfmttype.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mcf_getfmttype.sas macro
4 |
5 | SAS Macros
6 | @li mcf_getfmttype.sas
7 | @li mp_assert.sas
8 | @li mp_assertscope.sas
9 |
10 | **/
11 |
12 | %mp_assertscope(SNAPSHOT)
13 | %mcf_getfmttype(wrap=YES, insert_cmplib=YES)
14 | %mp_assertscope(COMPARE,ignorelist=SASJS_FUNCTIONS)
15 |
16 | %mp_assert(
17 | iftrue=(%sysfunc(mcf_getfmttype(DATE9.))=DATE),
18 | desc=Check DATE format
19 | )
20 | %mp_assert(
21 | iftrue=(%sysfunc(mcf_getfmttype($6))=CHAR),
22 | desc=Check CHAR format
23 | )
24 | %mp_assert(
25 | iftrue=(%sysfunc(mcf_getfmttype(8.))=NUM),
26 | desc=Check NUM format
27 | )
28 | %mp_assert(
29 | iftrue=(%sysfunc(mcf_getfmttype(E8601DT))=DATETIME),
30 | desc=Check DATETIME format
31 | )
32 |
33 | /* test 2 - compile again test for warnings */
34 | %mcf_getfmttype(wrap=YES, insert_cmplib=YES)
35 |
36 | %mp_assert(
37 | iftrue=(&syscc=0),
38 | desc=Check syscc=0 after re-initialisation
39 | )
--------------------------------------------------------------------------------
/tests/base/mcf_init.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mcf_init.sas macro
4 |
5 | SAS Macros
6 | @li mcf_init.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | %mp_assert(
12 | iftrue=(%mcf_init(test)=0),
13 | desc=Check if new func returns 0
14 | )
15 | %mp_assert(
16 | iftrue=(&syscc=0),
17 | desc=No errs on basic invocation
18 | )
19 | %mp_assert(
20 | iftrue=(%mcf_init(test)=1),
21 | desc=Check if second invocation returns 1
22 | )
23 | %mp_assert(
24 | iftrue=(&syscc=0),
25 | desc=No errs on second invocation
26 | )
27 | %mp_assert(
28 | iftrue=(%mcf_init(test2)=0),
29 | desc=Check if new invocation returns 0
30 | )
31 | %mp_assert(
32 | iftrue=(%mcf_init(test2)=1),
33 | desc=Check if second new invocation returns 1
34 | )
35 | %mp_assert(
36 | iftrue=(%mcf_init(test)=1),
37 | desc=Check original returns 1
38 | )
39 | %mp_assert(
40 | iftrue=(%mcf_init(t)=1),
41 | desc=Check subset returns 1
42 | )
43 | %mp_assert(
44 | iftrue=(&syscc=0),
45 | desc=No errs at end
46 | )
--------------------------------------------------------------------------------
/tests/base/mcf_length.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mcf_length.sas macro
4 |
5 | SAS Macros
6 | @li mcf_length.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | %mcf_length(wrap=YES, insert_cmplib=YES)
12 |
13 | data test;
14 | call symputx('null',mcf_length(.));
15 | call symputx('special',mcf_length(._));
16 | call symputx('three',mcf_length(1));
17 | call symputx('four',mcf_length(10000000));
18 | call symputx('five',mcf_length(12345678));
19 | call symputx('six',mcf_length(1234567890));
20 | call symputx('seven',mcf_length(12345678901234));
21 | call symputx('eight',mcf_length(12345678901234567));
22 | run;
23 |
24 | %mp_assert(
25 | iftrue=(%str(&null)=%str(0)),
26 | desc=Check if NULL returns 0
27 | )
28 | %mp_assert(
29 | iftrue=(%str(&special)=%str(3)),
30 | desc=Check if special missing ._ returns 3
31 | )
32 | %mp_assert(
33 | iftrue=(%str(&three)=%str(3)),
34 | desc=Check for length 3
35 | )
36 | %mp_assert(
37 | iftrue=(%str(&four)=%str(4)),
38 | desc=Check for length 4
39 | )
40 | %mp_assert(
41 | iftrue=(%str(&five)=%str(5)),
42 | desc=Check for length 5
43 | )
44 | %mp_assert(
45 | iftrue=(%str(&six)=%str(6)),
46 | desc=Check for length 6
47 | )
48 | %mp_assert(
49 | iftrue=(%str(&seven)=%str(7)),
50 | desc=Check for length 3
51 | )
52 | %mp_assert(
53 | iftrue=(%str(&eight)=%str(8)),
54 | desc=Check for length 8
55 | )
56 | %mp_assert(
57 | iftrue=(&syscc=0),
58 | desc=Check syscc=0 before re-initialisation
59 | )
60 |
61 | /* test 2 - compile again test for warnings */
62 | %mcf_length(wrap=YES, insert_cmplib=YES)
63 |
64 | %mp_assert(
65 | iftrue=(&syscc=0),
66 | desc=Check syscc=0 after re-initialisation
67 | )
--------------------------------------------------------------------------------
/tests/base/mcf_string2file.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mcf_string2file macro
4 |
5 | SAS Macros
6 | @li mcf_string2file.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 |
12 | %mcf_string2file(wrap=YES, insert_cmplib=YES)
13 |
14 | data _null_;
15 | rc=mcf_string2file(
16 | "%sysfunc(pathname(work))/newfile.txt"
17 | , "line1"
18 | , "APPEND");
19 | rc=mcf_string2file(
20 | "%sysfunc(pathname(work))/newfile.txt"
21 | , "line2"
22 | , "APPEND");
23 | run;
24 |
25 | data _null_;
26 | infile "%sysfunc(pathname(work))/newfile.txt";
27 | input;
28 | if _n_=2 then call symputx('val',_infile_);
29 | run;
30 |
31 | %mp_assert(
32 | iftrue=(%str(&val)=%str(line2)),
33 | desc=Check if APPEND works
34 | )
35 |
36 | data _null_;
37 | rc=mcf_string2file(
38 | "%sysfunc(pathname(work))/newfile.txt"
39 | , "creating"
40 | , "CREATE");
41 | run;
42 |
43 | data _null_;
44 | infile "%sysfunc(pathname(work))/newfile.txt";
45 | input;
46 | if _n_=1 then call symputx('val2',_infile_);
47 | run;
48 |
49 | %mp_assert(
50 | iftrue=(%str(&val2)=%str(creating)),
51 | desc=Check if CREATE works
52 | )
--------------------------------------------------------------------------------
/tests/base/mf_dedup.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_dedup macro
4 |
5 | SAS Macros
6 | @li mf_dedup.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | %let str=One two one two and through and through;
12 |
13 | %mp_assert(
14 | iftrue=("%mf_dedup(&str)"="One two one and through"),
15 | desc=Basic test,
16 | outds=work.test_results
17 | )
18 |
19 | %mp_assert(
20 | iftrue=("%mf_dedup(&str,outdlm=%str(,))"="One,two,one,and,through"),
21 | desc=Outdlm test,
22 | outds=work.test_results
23 | )
--------------------------------------------------------------------------------
/tests/base/mf_deletefile.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_deletefile.sas macro
4 |
5 | SAS Macros
6 | @li mf_deletefile.sas
7 | @li mf_writefile.sas
8 | @li mp_assert.sas
9 | @li mp_assertscope.sas
10 |
11 | **/
12 |
13 | %let test1file=&sasjswork/myfile1.txt;
14 |
15 | %mf_writefile(&test1file,l1=some content)
16 |
17 | %mp_assert(
18 | iftrue=(%sysfunc(fileexist(&test1file))=1),
19 | desc=Check &test1file exists
20 | )
21 |
22 | %mp_assertscope(SNAPSHOT)
23 | %mf_deletefile(&test1file)
24 | %mp_assertscope(COMPARE)
25 |
26 | %mp_assert(
27 | iftrue=(%sysfunc(fileexist(&test1file))=0),
28 | desc=Check &test1file no longer exists
29 | )
30 |
--------------------------------------------------------------------------------
/tests/base/mf_existds.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_existfileref macro
4 |
5 | SAS Macros
6 | @li mf_existds.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | data work.testme;
12 | x=1;
13 | run;
14 |
15 | %mp_assert(
16 | iftrue=(%mf_existds(work.testme)=1),
17 | desc=Checking existing dataset exists,
18 | outds=work.test_results
19 | )
20 |
21 | %mp_assert(
22 | iftrue=(%mf_existds(work.try2testme)=0),
23 | desc=Checking non existing dataset does not exist,
24 | outds=work.test_results
25 | )
--------------------------------------------------------------------------------
/tests/base/mf_existfileref.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_existfileref macro
4 |
5 | SAS Macros
6 | @li mf_existfileref.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | filename ref1 temp;
12 | filename ref2 temp;
13 |
14 | data _null_;
15 | file ref1;
16 | put 'exists';
17 | run;
18 |
19 | %mp_assert(
20 | iftrue=(%mf_existfileref(ref1)=1),
21 | desc=Checking fileref WITH target file exists,
22 | outds=work.test_results
23 | )
24 |
25 | %mp_assert(
26 | iftrue=(%mf_existfileref(ref2)=1),
27 | desc=Checking fileref WITHOUT target file exists,
28 | outds=work.test_results
29 | )
30 |
31 | %mp_assert(
32 | iftrue=(%mf_existfileref(ref3)=0),
33 | desc=Checking non-existant fref does not exist,
34 | outds=work.test_results
35 | )
36 |
--------------------------------------------------------------------------------
/tests/base/mf_existfunction.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_existfunction macro
4 |
5 | SAS Macros
6 | @li mf_existfunction.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | %mp_assert(
12 | iftrue=(%mf_existfunction(CAT)=1),
13 | desc=Checking if CAT function exists,
14 | outds=work.test_results
15 | )
16 |
17 | %mp_assert(
18 | iftrue=(%mf_existfunction(DOG)=0),
19 | desc=Checking DOG function does not exist,
20 | outds=work.test_results
21 | )
22 |
23 |
--------------------------------------------------------------------------------
/tests/base/mf_existvar.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_existvar macro
4 |
5 | SAS Macros
6 | @li mf_existvar.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 |
12 | %mp_assert(
13 | iftrue=(%mf_existvar(sashelp.class,age)>0),
14 | desc=Checking existing var exists
15 | )
16 |
17 | %mp_assert(
18 | iftrue=(%mf_existvar(sashelp.class,isjustanumber)=0),
19 | desc=Checking non existing var does not exist
20 | )
21 |
22 | data work.lockcheck;
23 | a=1;
24 | output;
25 | stop;
26 | run;
27 |
28 | %mp_assert(
29 | iftrue=(%mf_existvar(work.lockcheck,)=0),
30 | desc=Checking non-provided var does not exist
31 | )
32 |
33 | proc sql;
34 | update work.lockcheck set a=2;
35 |
36 | %mp_assert(
37 | iftrue=(&syscc=0),
38 | desc=Checking the lock was released,
39 | outds=work.test_results
40 | )
--------------------------------------------------------------------------------
/tests/base/mf_fmtdttm.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_fmtdttm macro
4 |
5 | SAS Macros
6 | @li mf_fmtdttm.sas
7 | @li mp_assert.sas
8 | @li mp_assertscope.sas
9 |
10 | **/
11 |
12 | %global test1;
13 |
14 | %mp_assertscope(SNAPSHOT)
15 | %let test1=%mf_fmtdttm();
16 | %mp_assertscope(COMPARE,ignorelist=test1)
17 |
18 | %mp_assert(
19 | iftrue=("&test1"="DATETIME19.3" or "&test1"="E8601DT26.6"),
20 | desc=Basic test,
21 | outds=work.test_results
22 | )
23 |
--------------------------------------------------------------------------------
/tests/base/mf_getapploc.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_getapploc macro
4 |
5 | SAS Macros
6 | @li mf_getapploc.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | %mp_assert(
12 | iftrue=(
13 | "%mf_getapploc(/some/loc/tests/services/x/service)"="/some/loc"
14 | ),
15 | desc=Checking test appLoc matches,
16 | outds=work.test_results
17 | )
18 |
19 | %mp_assert(
20 | iftrue=(
21 | "%mf_getapploc(/some/loc/tests/services/tests/service)"="/some/loc"
22 | ),
23 | desc=Checking nested services appLoc matches,
24 | outds=work.test_results
25 | )
26 |
27 | %mp_assert(
28 | iftrue=(
29 | "%mf_getapploc(/some/area/services/admin/service)"="/some/area"
30 | ),
31 | desc=Checking services appLoc matches,
32 | outds=work.test_results
33 | )
34 |
35 | %mp_assert(
36 | iftrue=(
37 | "%mf_getapploc(/some/area/jobs/jobs/job)"="/some/area"
38 | ),
39 | desc=Checking jobs appLoc matches,
40 | outds=work.test_results
41 | )
42 |
43 | %mp_assert(
44 | iftrue=(
45 | "%mf_getapploc(/some/area/tests/macros/somemacro.sas)"="/some/area"
46 | ),
47 | desc=Checking tests/macros appLoc matches (which has no subfolder),
48 | outds=work.test_results
49 | )
50 |
51 | %mp_assert(
52 | iftrue=(
53 | "%mf_getapploc(/some/area/tests/testsetup)"="/some/area"
54 | ),
55 | desc=Checking tests/testsetup operation,
56 | outds=work.test_results
57 | )
58 |
59 | %mp_assert(
60 | iftrue=(
61 | "%mf_getapploc(/some/area/tests/testteardown)"="/some/area"
62 | ),
63 | desc=Checking tests/teardown operation,
64 | outds=work.test_results
65 | )
--------------------------------------------------------------------------------
/tests/base/mf_getfilesize.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_getfilesize macro
4 |
5 | SAS Macros
6 | @li mf_getfilesize.sas
7 | @li mp_assert.sas
8 | @li mp_assertscope.sas
9 |
10 | **/
11 |
12 | data test;
13 | x=1;
14 | run;
15 |
16 | %mp_assertscope(SNAPSHOT)
17 | %put %mf_getfilesize(libds=work.test)
18 | %mp_assertscope(COMPARE)
19 |
20 | %mp_assert(
21 | iftrue=(&syscc=0),
22 | desc=Checking syscc
23 | )
24 |
25 | %put %mf_getfilesize(libds=test);
26 |
27 | %mp_assert(
28 | iftrue=(&syscc=0),
29 | desc=Checking syscc with one level name
30 | )
--------------------------------------------------------------------------------
/tests/base/mf_getfmtlist.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_getfmtlist macro
4 |
5 | SAS Macros
6 | @li mf_getfmtlist.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | %mp_assert(
12 | iftrue=(
13 | "%mf_getfmtlist(sashelp.prdsale)"="DOLLAR $CHAR W MONNAME"
14 | ),
15 | desc=Checking basic numeric,
16 | outds=work.test_results
17 | )
18 |
19 | %mp_assert(
20 | iftrue=(
21 | "%mf_getfmtlist(sashelp.shoes)"="$CHAR BEST DOLLAR"
22 | ),
23 | desc=Checking basic char,
24 | outds=work.test_results
25 | )
26 |
27 | %mp_assert(
28 | iftrue=(
29 | "%mf_getfmtlist(sashelp.demographics)"="BEST Z $CHAR COMMA PERCENTN"
30 | ),
31 | desc=Checking longer numeric,
32 | outds=work.test_results
33 | )
--------------------------------------------------------------------------------
/tests/base/mf_getfmtname.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_getfmtname macro
4 |
5 | SAS Macros
6 | @li mf_getfmtname.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | %mp_assert(
12 | iftrue=(
13 | "%mf_getfmtname(8.)"="W"
14 | ),
15 | desc=Checking basic numeric,
16 | outds=work.test_results
17 | )
18 |
19 | %mp_assert(
20 | iftrue=(
21 | "%mf_getfmtname($4.)"="$CHAR"
22 | ),
23 | desc=Checking basic char,
24 | outds=work.test_results
25 | )
26 |
27 | %mp_assert(
28 | iftrue=(
29 | "%mf_getfmtname(comma14.10)"="COMMA"
30 | ),
31 | desc=Checking longer numeric,
32 | outds=work.test_results
33 | )
--------------------------------------------------------------------------------
/tests/base/mf_getgitbranch.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_getgitbranch.sas macro
4 |
5 | SAS Macros
6 | @li mf_getgitbranch.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | /* grab core repo */
12 | %let gitdir=%sysfunc(pathname(work))/core;
13 | %let repo=https://github.com/sasjs/core;
14 | %put source clone rc=%sysfunc(GITFN_CLONE(&repo,&gitdir));
15 |
16 | %mp_assert(
17 | iftrue=(%mf_getgitbranch(&gitdir)=main),
18 | desc=Checking correct branch was obtained,
19 | outds=work.test_results
20 | )
21 |
--------------------------------------------------------------------------------
/tests/base/mf_getuniquefileref.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_getuniquefileref macro
4 | @details To test performance you can also use the following macro:
5 |
6 | %macro x(prefix);
7 | %let now=%sysfunc(datetime());
8 | %do x=1 %to 1000;
9 | %let rc=%mf_getuniquefileref(prefix=&prefix);
10 | %end;
11 | %put %sysevalf(%sysfunc(datetime())-&now);
12 | %mend;
13 | %x(_)
14 | %x(0)
15 |
16 | SAS Macros
17 | @li mf_getuniquefileref.sas
18 | @li mp_assert.sas
19 |
20 | **/
21 |
22 | %mp_assert(
23 | iftrue=(
24 | "%substr(%mf_getuniquefileref(prefix=0),1,1)"="#"
25 | ),
26 | desc=Checking for a natively assigned fileref,
27 | outds=work.test_results
28 | )
29 |
30 | %mp_assert(
31 | iftrue=(
32 | "%substr(%mf_getuniquefileref(),1,1)"="_"
33 | ),
34 | desc=Checking for a default fileref,
35 | outds=work.test_results
36 | )
37 |
--------------------------------------------------------------------------------
/tests/base/mf_getuniquelibref.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_getuniquelibref macro
4 | @details To test performance you can also use the following macro:
5 |
6 | SAS Macros
7 | @li mf_getuniquelibref.sas
8 | @li mp_assert.sas
9 | @li mp_assertscope.sas
10 |
11 | **/
12 |
13 | /* check valid libs */
14 | %mp_assertscope(SNAPSHOT)
15 | %let libshort=%mf_getuniquelibref(prefix=lib);
16 | %mp_assertscope(COMPARE,ignorelist=LIBSHORT)
17 | libname &libshort (work);
18 | %mp_assert(
19 | iftrue=(&syscc=0),
20 | desc=Checking for valid libref &libshort,
21 | outds=work.test_results
22 | )
23 |
24 | %let lib7=%mf_getuniquelibref(prefix=libref7);
25 | libname &lib7 (work);
26 | %mp_assert(
27 | iftrue=(&syscc=0),
28 | desc=Checking for valid libref &lib7,
29 | outds=work.test_results
30 | )
31 |
32 |
33 | /* check for invalid libs */
34 |
35 | %let lib8=%mf_getuniquelibref(prefix=lib8char);
36 | %mp_assert(
37 | iftrue=(&lib8=0),
38 | desc=Invalid prefix (8 chars),
39 | outds=work.test_results
40 | )
41 |
42 | %let liblong=%mf_getuniquelibref(prefix=invalidlib);
43 | %mp_assert(
44 | iftrue=(&liblong=0),
45 | desc=Checking for invalid libref (long),
46 | outds=work.test_results
47 | )
48 |
49 | %let badlib=%mf_getuniquelibref(prefix=8adlib);
50 | %mp_assert(
51 | iftrue=(&badlib=0),
52 | desc=Checking for invalid libref (8adlib),
53 | outds=work.test_results
54 | )
--------------------------------------------------------------------------------
/tests/base/mf_getvarcount.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_getvarlist macro
4 |
5 | SAS Macros
6 | @li mf_getvarcount.sas
7 | @li mp_assertscope.sas
8 |
9 | **/
10 |
11 | data work.all work.nums(keep=num1 num2) work.chars(keep=char1 char2);
12 | length num1 num2 8 char1 char2 char3 $4;
13 | call missing (of _all_);
14 | output;
15 | run;
16 |
17 | %mp_assertscope(SNAPSHOT)
18 | %put scope check:%mf_getvarcount(work.all);
19 | %mp_assertscope(COMPARE)
20 |
21 | %mp_assert(
22 | iftrue=(%mf_getvarcount(work.all)=5),
23 | desc=%str(Checking for mixed vars),
24 | outds=work.test_results
25 | )
26 | %mp_assert(
27 | iftrue=(%mf_getvarcount(work.all,typefilter=C)=3),
28 | desc=%str(Checking for char in mixed vars),
29 | outds=work.test_results
30 | )
31 | %mp_assert(
32 | iftrue=(%mf_getvarcount(work.all,typefilter=N)=2),
33 | desc=%str(Checking for num in mixed vars),
34 | outds=work.test_results
35 | )
36 | %mp_assert(
37 | iftrue=(%mf_getvarcount(work.nums,typefilter=c)=0),
38 | desc=%str(Checking for char in num vars),
39 | outds=work.test_results
40 | )
41 | %mp_assert(
42 | iftrue=(%mf_getvarcount(work.chars,typefilter=N)=0),
43 | desc=%str(Checking for num in char vars),
44 | outds=work.test_results
45 | )
46 |
47 |
--------------------------------------------------------------------------------
/tests/base/mf_increment.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_increment macro
4 |
5 | SAS Macros
6 | @li mf_increment.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | %let var=0;
12 |
13 | %mp_assert(
14 | iftrue=(
15 | "%mf_increment(var)"="1"
16 | ),
17 | desc=Checking basic mf_increment usage 1,
18 | outds=work.test_results
19 | )
20 |
21 | %mp_assert(
22 | iftrue=(
23 | "%mf_increment(var)"="2"
24 | ),
25 | desc=Checking basic mf_increment usage 2,
26 | outds=work.test_results
27 | )
28 |
29 | %mp_assert(
30 | iftrue=(
31 | "%mf_increment(var,incr=2)"="4"
32 | ),
33 | desc=Checking incr option,
34 | outds=work.test_results
35 | )
36 |
--------------------------------------------------------------------------------
/tests/base/mf_isint.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_isint macro
4 |
5 | SAS Macros
6 | @li mf_isint.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | %mp_assert(
12 | iftrue=(
13 | "%mf_isint(1)"="1"
14 | ),
15 | desc=Checking basic mf_isint(1),
16 | outds=work.test_results
17 | )
18 |
19 | %mp_assert(
20 | iftrue=(
21 | "%mf_isint(1.1)"="0"
22 | ),
23 | desc=Checking basic mf_isint(1.1),
24 | outds=work.test_results
25 | )
26 |
27 | %mp_assert(
28 | iftrue=(
29 | "%mf_isint(-1)"="1"
30 | ),
31 | desc=Checking mf_isint(-1),
32 | outds=work.test_results
33 | )
34 |
35 | %mp_assert(
36 | iftrue=(
37 | "%mf_isint()"="0"
38 | ),
39 | desc=Checking mf_isint(),
40 | outds=work.test_results
41 | )
--------------------------------------------------------------------------------
/tests/base/mf_islibds.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_islibds macro
4 |
5 | %put %mf_islibds(work.something)=1;
6 | %put %mf_islibds(nolib)=0;
7 | %put %mf_islibds(badlibref.ds)=0;
8 | %put %mf_islibds(w.t.f)=0;
9 |
10 | SAS Macros
11 | @li mf_islibds.sas
12 | @li mp_assert.sas
13 |
14 | **/
15 |
16 | %mp_assert(
17 | iftrue=(
18 | %mf_islibds(work.something)=1
19 | ),
20 | desc=%str(Checking mf_islibds(work.something)=1),
21 | outds=work.test_results
22 | )
23 |
24 | %mp_assert(
25 | iftrue=(
26 | %mf_islibds(nolib)=0
27 | ),
28 | desc=%str(Checking mf_islibds(nolib)=0),
29 | outds=work.test_results
30 | )
31 |
32 | %mp_assert(
33 | iftrue=(
34 | %mf_islibds(badlibref.ds)=0
35 | ),
36 | desc=%str(Checking mf_islibds(badlibref.ds)=0),
37 | outds=work.test_results
38 | )
39 |
40 | %mp_assert(
41 | iftrue=(
42 | %mf_islibds(w.t.f)=0
43 | ),
44 | desc=%str(Checking mf_islibds(w.t.f)=0),
45 | outds=work.test_results
46 | )
47 |
--------------------------------------------------------------------------------
/tests/base/mf_mimetype.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_mimetype macro
4 |
5 | SAS Macros
6 | @li mf_mimetype.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 |
12 | %mp_assert(
13 | iftrue=("%mf_mimetype(XLS)"="application/vnd.ms-excel",
14 | desc=Checking correct value
15 | )
16 |
17 |
--------------------------------------------------------------------------------
/tests/base/mf_readfile.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_readfile.sas macro
4 |
5 | SAS Macros
6 | @li mf_readfile.sas
7 | @li mf_writefile.sas
8 | @li mp_assert.sas
9 | @li mp_assertscope.sas
10 |
11 | **/
12 |
13 | %let f=&sasjswork/myfile.txt;
14 |
15 | %mf_writefile(&f,l1=some content,l2=more content)
16 | data _null_;
17 | infile "&f";
18 | input;
19 | putlog _infile_;
20 | run;
21 |
22 | %mp_assert(
23 | iftrue=(&syscc=0),
24 | desc=Check code ran without errors,
25 | outds=work.test_results
26 | )
27 |
28 | /* test for scope leakage */
29 | %global result;
30 | %mp_assertscope(SNAPSHOT)
31 | %put %mf_readfile(&f);
32 | %mp_assertscope(COMPARE)
33 |
34 | /* test result */
35 | %mp_assert(
36 | iftrue=(%mf_readfile(&f)=some content),
37 | desc=Checking first line was ingested successfully,
38 | outds=work.test_results
39 | )
40 |
41 |
--------------------------------------------------------------------------------
/tests/base/mf_verifymacvars.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_verifymacvars macro
4 |
5 | SAS Macros
6 | @li mf_verifymacvars.sas
7 | @li mp_assert.sas
8 | @li mp_assertscope.sas
9 |
10 | **/
11 |
12 | %let var1=x;
13 | %let var2=y;
14 |
15 | %mp_assertscope(SNAPSHOT)
16 | %mp_assert(
17 | iftrue=(%mf_verifymacvars(var1 var2)=1),
18 | desc=Checking macvars exist,
19 | outds=work.test_results
20 | )
21 | %mp_assertscope(COMPARE)
22 |
23 |
--------------------------------------------------------------------------------
/tests/base/mf_wordsinstr1andstr2.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_wordsinstr1andstr2 macro
4 |
5 | SAS Macros
6 | @li mf_wordsinstr1andstr2.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | %let x=%mf_wordsinstr1andstr2(str1=xx DOLLAR x $CHAR xxx W MONNAME
12 | ,str2=DOLLAR $CHAR W MONNAME xxxxxx
13 | );
14 | %mp_assert(
15 | iftrue=(
16 | "&x"="DOLLAR $CHAR W MONNAME"
17 | ),
18 | desc=Checking basic string,
19 | outds=work.test_results
20 | )
21 |
--------------------------------------------------------------------------------
/tests/base/mf_wordsinstr1butnotstr2.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mf_wordsinstr1butnotstr2 macro
4 |
5 | SAS Macros
6 | @li mf_wordsinstr1butnotstr2.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | %let x=%mf_wordsinstr1butnotstr2(str1=xx DOLLAR x $CHAR xxx W MONNAME
12 | ,str2=ff xx x xxx xxxxxx
13 | );
14 | %mp_assert(
15 | iftrue=(
16 | "&x"="DOLLAR $CHAR W MONNAME"
17 | ),
18 | desc=Checking basic string,
19 | outds=work.test_results
20 | )
21 |
--------------------------------------------------------------------------------
/tests/base/mp_abort.test.nofix.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_abort macro
4 | @details This is an unfixed problem with mp_abort when using the
5 | 'unclosed macro' technique. This is only relevant for 9.4m3 environments,
6 | which can suffer from hung multibridge sessions from %abort and endsas.
7 |
8 | The issue is that when called within a macro, within a %include, AND that
9 | macro contains subsequent logic, the service does not end cleanly - rather,
10 | we see:
11 |
12 | ERROR: %EVAL function has no expression to evaluate, or %IF statement has no condition.
13 | ERROR: The macro TEST will stop executing.
14 |
15 | We are not able to test this without a 9.4m3 environment, it is marked as
16 | nofix.
17 |
18 | SAS Macros
19 | @li mp_abort.sas
20 | @li mp_assert.sas
21 |
22 | **/
23 |
24 | %macro test();
25 |
26 | filename blah temp;
27 | data _null_;
28 | file blah;
29 | put '%mp_abort();';
30 | run;
31 | %inc blah;
32 |
33 | %if 1=1 %then %put Houston - we have a problem here;
34 | %mend test;
35 |
36 | %test()
--------------------------------------------------------------------------------
/tests/base/mp_aligndecimal.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_aligndecimal macro
4 | @details Creates an aligned variable and checks the number of leading blanks
5 |
6 | SAS Macros
7 | @li mp_aligndecimal.sas
8 | @li mp_assertcolvals.sas
9 | @li mp_assertscope.sas
10 |
11 | **/
12 |
13 |
14 |
15 | /* target values */
16 | data work.checkds;
17 | do checkval=' 0.56',' 123.45',' 123.4 ',' 1.2 ',' 0';
18 | output;
19 | end;
20 | run;
21 |
22 | /* raw values */
23 | data work.rawds;
24 | set work.checkds;
25 | tgtvar=cats(checkval);
26 | drop checkval;
27 | run;
28 | %mp_assertcolvals(work.rawds.tgtvar,
29 | checkvals=work.checkds.checkval,
30 | desc=No values match (ready to align),
31 | test=NOVAL
32 | )
33 |
34 | /* aligned values */
35 | %mp_assertscope(SNAPSHOT)
36 | data work.finalds;
37 | set work.rawds;
38 | %mp_aligndecimal(tgtvar,width=4)
39 | run;
40 | %mp_assertscope(COMPARE)
41 |
42 | %mp_assertcolvals(work.finalds.tgtvar,
43 | checkvals=work.checkds.checkval,
44 | desc=All values match (aligned),
45 | test=ALLVALS
46 | )
47 |
--------------------------------------------------------------------------------
/tests/base/mp_appendfile.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_appendfile.sas macro
4 |
5 | SAS Macros
6 | @li mp_appendfile.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 |
12 | filename tmp1 temp;
13 | filename tmp2 temp;
14 | filename tmp3 temp;
15 | data _null_; file tmp1; put 'base file';
16 | data _null_; file tmp2; put 'append1';
17 | data _null_; file tmp3; put 'append2';
18 | run;
19 | %mp_appendfile(baseref=tmp1, appendrefs=tmp2 tmp3)
20 | data _null_;
21 | infile tmp1;
22 | input;
23 | put _infile_;
24 | call symputx(cats('check',_n_),_infile_);
25 | run;
26 | %global check1 check2 check3;
27 | %mp_assert(
28 | iftrue=("&check1"="base file"),
29 | desc=Line 1 of file tmp1 is correct,
30 | outds=work.test_results
31 | )
32 | %mp_assert(
33 | iftrue=("&check2"="append1"),
34 | desc=Line 2 of file tmp1 is correct,
35 | outds=work.test_results
36 | )
37 | %mp_assert(
38 | iftrue=("&check3"="append2"),
39 | desc=Line 3 of file tmp1 is correct,
40 | outds=work.test_results
41 | )
--------------------------------------------------------------------------------
/tests/base/mp_applyformats.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_applyformats.sas macro
4 |
5 | SAS Macros
6 | @li mf_getvarformat.sas
7 | @li mp_applyformats.sas
8 | @li mp_assert.sas
9 | @li mp_getcols.sas
10 |
11 | **/
12 |
13 | /**
14 | * Test 1 Base case
15 | */
16 |
17 | data work.example;
18 | set sashelp.prdsale;
19 | format _all_;
20 | run;
21 | %let origfmt=%mf_getvarformat(work.example,month);
22 |
23 | %mp_getcols(sashelp.prdsale,outds=work.cols)
24 |
25 | data work.cols2;
26 | set work.cols;
27 | lib='WORK';
28 | ds='EXAMPLE';
29 | var=name;
30 | fmt=format;
31 | keep lib ds var fmt;
32 | run;
33 |
34 | %mp_applyformats(work.cols2)
35 |
36 | %mp_assert(
37 | iftrue=("&origfmt"=""),
38 | desc=Check that formats were cleared,
39 | outds=work.test_results
40 | )
41 | %mp_assert(
42 | iftrue=("%mf_getvarformat(work.example,month)"="MONNAME3."),
43 | desc=Check that formats were applied,
44 | outds=work.test_results
45 | )
--------------------------------------------------------------------------------
/tests/base/mp_assert.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_assert macro
4 | @details This is quite "meta".. it's just testing itself
5 |
6 | SAS Macros
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | %mp_assert(
12 | iftrue=(1=1),
13 | desc=Checking result was created,
14 | outds=work.test_results
15 | )
16 |
--------------------------------------------------------------------------------
/tests/base/mp_assertcolvals.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_assertcolvals macro
4 |
5 | SAS Macros
6 | @li mp_assertcolvals.sas
7 |
8 | **/
9 |
10 |
11 | data work.checkds;
12 | do checkval='Jane','James','Jill';
13 | output;
14 | end;
15 | run;
16 | %mp_assertcolvals(sashelp.class.name,
17 | checkvals=work.checkds.checkval,
18 | desc=At least one value has a match,
19 | test=ANYVAL
20 | )
21 |
22 | data work.check;
23 | do val='M','F';
24 | output;
25 | end;
26 | run;
27 | %mp_assertcolvals(sashelp.class.sex,
28 | checkvals=work.check.val,
29 | desc=All values have a match,
30 | test=ALLVALS
31 | )
32 |
33 |
--------------------------------------------------------------------------------
/tests/base/mp_assertdsobs.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_assertdsobs.sas macro
4 |
5 | SAS Macros
6 | @li mp_assertdsobs.sas
7 | @li mp_assertcolvals.sas
8 |
9 | **/
10 |
11 |
12 | data work.somedata;
13 | do x=1 to 15;
14 | output;
15 | end;
16 | run;
17 |
18 | %mp_assertdsobs(work.somedata,
19 | test=ATLEAST 15,
20 | outds=work.test_the_test
21 | )
22 |
23 | %mp_assertdsobs(work.somedata,
24 | test=ATMOST 15,
25 | outds=work.test_the_test
26 | )
27 |
28 | data work.check;
29 | val='PASS';
30 | run;
31 | %mp_assertcolvals(work.test_the_test.test_result,
32 | checkvals=work.check.val,
33 | desc=Testing ATLEAST / ATMOST for passes,
34 | test=ALLVALS
35 | )
36 |
37 | %mp_assertdsobs(work.somedata,
38 | test=ATLEAST 16,
39 | outds=work.test_the_test2
40 | )
41 | %mp_assertdsobs(work.somedata,
42 | test=ATMOST 14,
43 | outds=work.test_the_test2
44 | )
45 |
46 | data _null_;
47 | set work.test_the_test2;
48 | putlog (_all_)(=);
49 | run;
50 |
51 | data work.check2;
52 | val='FAIL';
53 | run;
54 | %mp_assertcolvals(work.test_the_test2.test_result,
55 | checkvals=work.check2.val,
56 | desc=Testing ATLEAST / ATMOST for failures,
57 | test=ALLVALS
58 | )
59 |
60 |
61 |
--------------------------------------------------------------------------------
/tests/base/mp_base64copy.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_base64copy.sas macro
4 |
5 | SAS Macros
6 | @li mp_base64copy.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 |
12 | /* TEST 1 - regular base64 decode */
13 |
14 | %let string1=base ik ally;
15 | filename tmp temp;
16 | data _null_;
17 | file tmp;
18 | put "&string1";
19 | run;
20 | %mp_base64copy(inref=tmp, outref=myref, action=ENCODE)
21 |
22 | data _null_;
23 | infile myref;
24 | input;
25 | put _infile_;
26 | run;
27 | %mp_base64copy(inref=myref, outref=mynewref, action=DECODE)
28 | data _null_;
29 | infile mynewref lrecl=5000;
30 | input;
31 | put _infile_;
32 | call symputx('string1_check',_infile_);
33 | stop;
34 | run;
35 | %mp_assert(
36 | iftrue=("&string1"="&string1_check"),
37 | desc=Basic String Compare,
38 | outds=work.test_results
39 | )
40 |
41 |
42 | /* multibyte string check */
43 |
44 | filename tmp2 temp lrecl=500;
45 | data _null_;
46 | file tmp2;
47 | put "'╤', '╔', '╗', '═', '╧', '╚', '╝', '║', '╟', '─', '┼', '║', '╢', '│'";
48 | run;
49 | %mp_base64copy(inref=tmp2, outref=myref2, action=ENCODE)
50 |
51 | %mp_base64copy(inref=myref2, outref=newref2, action=DECODE)
52 | data _null_;
53 | infile newref2 lrecl=5000;
54 | input;
55 | list;
56 | /* do not print the string to the log else viya 3.5 throws exception */
57 | if trim(_infile_)=
58 | "'╤', '╔', '╗', '═', '╧', '╚', '╝', '║', '╟', '─', '┼', '║', '╢', '│'"
59 | then call symputx('check2',1);
60 | else call symputx('check2',0);
61 | stop;
62 | run;
63 | %mp_assert(
64 | iftrue=("&check2"="1"),
65 | desc=Double Byte String Compare,
66 | outds=work.test_results
67 | )
--------------------------------------------------------------------------------
/tests/base/mp_cleancsv.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_cleancsv.sas macro
4 | @details Credit for test 1 goes to
5 | [Tom](https://communities.sas.com/t5/user/viewprofilepage/user-id/159) from
6 | SAS Communities:
7 | https://communities.sas.com/t5/SAS-Programming/Removing-embedded-carriage-returns/m-p/824790#M325761
8 |
9 | SAS Macros
10 | @li mf_nobs.sas
11 | @li mp_cleancsv.sas
12 | @li mp_assert.sas
13 | @li mp_assertscope.sas
14 |
15 | **/
16 |
17 | /* test 1 - cope with empty rows on CR formatted file */
18 |
19 | filename crlf "%sysfunc(pathname(work))/crlf";
20 | filename cr "%sysfunc(pathname(work))/cr";
21 | data _null_;
22 | file cr termstr=cr ;
23 | put 'line 1'///'line 4'/'line 5';
24 | run;
25 |
26 | %mp_assertscope(SNAPSHOT)
27 | %mp_cleancsv(in=cr,out=crlf)
28 | %mp_assertscope(COMPARE)
29 |
30 | /* 5 rows as all converted to OD0A */
31 | data test1;
32 | infile "%sysfunc(pathname(work))/crlf" lrecl=100 termstr=crlf;
33 | input;
34 | list;
35 | run;
36 |
37 | %put test1=%mf_nobs(test1);
38 |
39 | %mp_assert(
40 | iftrue=(%mf_nobs(work.test1)=5),
41 | desc=Checking blank rows on CR formatted file,
42 | outds=work.test_results
43 | )
44 |
--------------------------------------------------------------------------------
/tests/base/mp_cntlout.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_cntlout.sas macro
4 |
5 | SAS Macros
6 | @li mf_nobs.sas
7 | @li mp_cntlout.sas
8 | @li mp_assert.sas
9 | @li mp_assertscope.sas
10 |
11 | **/
12 |
13 | libname perm (work);
14 | data work.loadfmts;
15 | length fmtname $32;
16 | eexcl='Y';
17 | type='N';
18 | do i=1 to 100;
19 | fmtname=cats('SASJS_',i,'X');
20 | do j=1 to 100;
21 | start=cats(j);
22 | end=cats(j+1);
23 | label= cats('Dummy ',start);
24 | output;
25 | end;
26 | end;
27 | run;
28 | proc format cntlin=work.loadfmts library=perm.testcat;
29 | run;
30 |
31 | %mp_assertscope(SNAPSHOT)
32 | %mp_cntlout(libcat=perm.testcat,cntlout=work.cntlout)
33 | %mp_assertscope(COMPARE)
34 |
35 | %mp_assert(
36 | iftrue=(%mf_nobs(work.cntlout)=10000),
37 | desc=Checking first hash diff,
38 | outds=work.test_results
39 | )
40 |
--------------------------------------------------------------------------------
/tests/base/mp_copyfolder.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_copyfolder.sas macro
4 |
5 | SAS Macros
6 | @li mp_copyfolder.sas
7 | @li mf_mkdir.sas
8 | @li mf_nobs.sas
9 | @li mp_assert.sas
10 | @li mp_dirlist.sas
11 |
12 | **/
13 |
14 | /**
15 | * make a directory structure
16 | */
17 |
18 | %let root=%sysfunc(pathname(work))/top;
19 | %mf_mkdir(&root)
20 | %mf_mkdir(&root/a)
21 | %mf_mkdir(&root/b)
22 | %mf_mkdir(&root/a/d)
23 | %mf_mkdir(&root/a/e)
24 | %mf_mkdir(&root/a/e/f)
25 | data "&root/a/e/f/ds1.sas7bdat";x=1;
26 | data "&root/a/e/ds2.sas7bdat";x=1;
27 | data "&root/a/ds3.sas7bdat";x=1;
28 | run;
29 |
30 | %mp_dirlist(path=&root, outds=myTable, maxdepth=MAX)
31 |
32 | %mp_assert(
33 | iftrue=(%mf_nobs(work.mytable)=8),
34 | desc=Temp data successfully created,
35 | outds=work.test_results
36 | )
37 |
38 | /**
39 | * copy it
40 | */
41 | %let newfolder=%sysfunc(pathname(work))/new;
42 | %mp_copyfolder(&root,&newfolder)
43 |
44 | %mp_dirlist(path=&newfolder, outds=work.myTable2, maxdepth=MAX)
45 |
46 | %mp_assert(
47 | iftrue=(%mf_nobs(work.mytable2)=8),
48 | desc=Folder successfully copied,
49 | outds=work.test_results
50 | )
51 |
52 |
53 |
--------------------------------------------------------------------------------
/tests/base/mp_coretable.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_coretable.sas macro
4 |
5 | SAS Macros
6 | @li mf_existds.sas
7 | @li mp_coretable.sas
8 | @li mp_assert.sas
9 |
10 | **/
11 |
12 |
13 | %mp_coretable(LOCKTABLE,libds=work.lock)
14 | %mp_assert(
15 | iftrue=(%mf_existds(work.lock)=1),
16 | desc=Lock table created,
17 | outds=work.test_results
18 | )
19 | %mp_coretable(LOCKTABLE)
20 | %mp_assert(
21 | iftrue=("&syscc"="0"),
22 | desc=DDL export ran without errors,
23 | outds=work.test_results
24 | )
25 |
26 | %mp_coretable(FILTER_SUMMARY,libds=work.sum)
27 | %mp_assert(
28 | iftrue=(%mf_existds(work.sum)=1),
29 | desc=Filter summary table created,
30 | outds=work.test_results
31 | )
--------------------------------------------------------------------------------
/tests/base/mp_createwebservice.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing ms_createwebservice.sas macro
4 |
5 | SAS Macros
6 | @li mf_getuniquefileref.sas
7 | @li mp_assertscope.sas
8 | @li mp_createwebservice.sas
9 |
10 | **/
11 |
12 | %let path=&mcTestAppLoc/mp_createwebservice;
13 | %let name=myservice;
14 | %let fref=%mf_getuniquefileref();
15 |
16 | data _null_;
17 | file &fref lrecl=3000;
18 | put '%put hello world;';
19 | run;
20 |
21 | %mp_assertscope(SNAPSHOT)
22 | %mp_createwebservice(path=&path,name=&name,code=&fref,mdebug=&sasjs_mdebug)
23 | %mp_assertscope(COMPARE)
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/tests/base/mp_deletefolder.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_deletefolder.sas macro
4 |
5 | SAS Macros
6 | @li mp_deletefolder.sas
7 | @li mf_mkdir.sas
8 | @li mf_nobs.sas
9 | @li mp_assert.sas
10 | @li mp_dirlist.sas
11 |
12 | **/
13 |
14 | /**
15 | * make a directory structure
16 | */
17 |
18 | %let root=%sysfunc(pathname(work))/top;
19 | %mf_mkdir(&root)
20 | %mf_mkdir(&root/a)
21 | %mf_mkdir(&root/b)
22 | %mf_mkdir(&root/a/d)
23 | %mf_mkdir(&root/a/e)
24 | %mf_mkdir(&root/a/e/f)
25 | data "&root/a/e/f/ds1.sas7bdat";
26 | x=1;
27 | run;
28 |
29 | %mp_dirlist(path=&root, outds=myTable, maxdepth=MAX)
30 |
31 | %mp_assert(
32 | iftrue=(%mf_nobs(work.mytable)=6),
33 | desc=Temp data successfully created,
34 | outds=work.test_results
35 | )
36 |
37 | %mp_deletefolder(&root/a)
38 |
39 | %mp_dirlist(path=&root, outds=work.myTable2, maxdepth=MAX)
40 |
41 | data _null_;
42 | set work.mytable2;
43 | putlog (_all_)(=);
44 | run;
45 |
46 | %mp_assert(
47 | iftrue=(%mf_nobs(work.mytable2)=1),
48 | desc=Subfolder and contents successfully deleted,
49 | outds=work.test_results
50 | )
51 |
--------------------------------------------------------------------------------
/tests/base/mp_dictionary.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_dictionary.sas macro
4 |
5 | SAS Macros
6 | @li mp_dictionary.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | libname test (work);
12 | %mp_dictionary(lib=test)
13 |
14 | proc sql;
15 | create table work.compare1 as select * from test.styles;
16 | create table work.compare2 as select * from dictionary.styles;
17 |
18 | proc compare base=compare1 compare=compare2;
19 | run;
20 | %put _all_;
21 |
22 | %mp_assert(
23 | iftrue=(%mf_existds(&sysinfo)=0),
24 | desc=Compare was exact,
25 | outds=work.test_results
26 | )
27 |
--------------------------------------------------------------------------------
/tests/base/mp_dirlist.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_dirlist.sas macro
4 |
5 | SAS Macros
6 | @li mf_nobs.sas
7 | @li mf_mkdir.sas
8 | @li mp_dirlist.sas
9 | @li mp_assert.sas
10 |
11 | **/
12 |
13 | /**
14 | * make a directory structure
15 | */
16 |
17 | %let root=%sysfunc(pathname(work))/top;
18 | %mf_mkdir(&root)
19 | %mf_mkdir(&root/a)
20 | %mf_mkdir(&root/b)
21 | %mf_mkdir(&root/a/d)
22 | %mf_mkdir(&root/a/e)
23 | %mf_mkdir(&root/a/e/f)
24 | libname test "&root/a/e/f";
25 | data test.ds1;
26 | x=1;
27 | run;
28 |
29 | %mp_dirlist(path=&root, outds=myTable, maxdepth=MAX)
30 |
31 | %mp_assert(
32 | iftrue=(%mf_nobs(work.mytable)=6),
33 | desc=All levels returned,
34 | outds=work.test_results
35 | )
36 |
37 | %mp_dirlist(path=&root, outds=myTable2, maxdepth=2)
38 |
39 | %mp_assert(
40 | iftrue=(%mf_nobs(work.mytable2)=5),
41 | desc=Top two levels returned,
42 | outds=work.test_results
43 | )
44 |
45 | %mp_dirlist(path=&root, outds=work.myTable3, maxdepth=0)
46 |
47 | %mp_assert(
48 | iftrue=(%mf_nobs(work.mytable3)=2),
49 | desc=Top level returned,
50 | outds=work.test_results
51 | )
52 |
53 | %mp_dirlist(path=&root/b, outds=work.myTable4)
54 | %mp_assert(
55 | iftrue=(%mf_nobs(work.mytable4)=0),
56 | desc=Empty table for empty directory,
57 | outds=work.test_results
58 | )
59 |
60 | %mp_dirlist(path=&root/notexisting, outds=work.myTable5)
61 | %mp_assert(
62 | iftrue=(%mf_nobs(work.mytable5)=0),
63 | desc=Empty table for non-existing directory,
64 | outds=work.test_results
65 | )
66 |
--------------------------------------------------------------------------------
/tests/base/mp_ds2cards.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_ds2cards.sas macro
4 |
5 | SAS Macros
6 | @li mp_ds2cards.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | /**
12 | * test 1 - rebuild an existing dataset
13 | * Cars is a great dataset - it contains leading spaces, and formatted numerics
14 | */
15 |
16 | %mp_ds2cards(base_ds=sashelp.cars
17 | , tgt_ds=work.test
18 | , cards_file= "%sysfunc(pathname(work))/cars.sas"
19 | , showlog=NO
20 | )
21 | %inc "%sysfunc(pathname(work))/cars.sas"/source2 lrecl=32767;
22 |
23 | proc compare base=sashelp.cars compare=work.test;
24 | quit;
25 |
26 | %mp_assert(
27 | iftrue=(&sysinfo=1),
28 | desc=sashelp.cars is identical except for ds label,
29 | outds=work.test_results
30 | )
31 |
32 | /**
33 | * test 2 - binary data compare
34 | */
35 | data work.binarybase;
36 | format bin $hex500. z $hex.;
37 | do x=1 to 250;
38 | z=byte(x);
39 | bin=trim(bin)!!z;
40 | output;
41 | end;
42 | run;
43 |
44 | %mp_ds2cards(base_ds=work.binarybase
45 | , showlog=YES
46 | , cards_file="%sysfunc(pathname(work))/c2.sas"
47 | , tgt_ds=work.binarycompare
48 | , append=
49 | )
50 |
51 | %inc "%sysfunc(pathname(work))/c2.sas"/source2 lrecl=32767;
52 |
53 | proc compare base=work.binarybase compare=work.binarycompare;
54 | run;
55 |
56 | %mp_assert(
57 | iftrue=(&sysinfo=0),
58 | desc=work.binarybase dataset is identical,
59 | outds=work.test_results
60 | )
--------------------------------------------------------------------------------
/tests/base/mp_ds2csv.test.2.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_ds2csv.sas macro
4 |
5 | SAS Macros
6 | @li mp_ds2csv.sas
7 | @li mp_assert.sas
8 | @li mp_assertscope.sas
9 |
10 | **/
11 |
12 | data work.shortnum;
13 | length a 3 b 4 c 8;
14 | a=1;b=2;c=3;
15 | output;
16 | stop;
17 | run;
18 |
19 | /**
20 | * Test 1 - default CSV
21 | */
22 |
23 | %mp_ds2csv(work.shortnum,outfile="&sasjswork/test1.csv",headerformat=SASJS)
24 |
25 | %let test1b=FAIL;
26 | data _null_;
27 | infile "&sasjswork/test1.csv";
28 | input;
29 | list;
30 | if _n_=1 then call symputx('test1a',_infile_);
31 | else if _infile_=:'1,2,3' then call symputx('test1b','PASS');
32 | run;
33 |
34 | %mp_assert(
35 | iftrue=("&test1a"="A:best3. B:best4. C:best."),
36 | desc=Checking header row Test 1,
37 | outds=work.test_results
38 | )
39 | %mp_assert(
40 | iftrue=("&test1b"="PASS"),
41 | desc=Checking data row Test 1,
42 | outds=work.test_results
43 | )
44 |
--------------------------------------------------------------------------------
/tests/base/mp_ds2fmtds.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_ds2fmtds.sas macro
4 |
5 | SAS Macros
6 | @li mp_ds2fmtds.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | proc sql;
12 | create table test as select * from dictionary.tables where libname='SASHELP';
13 |
14 | filename inc temp;
15 | data _null_;
16 | set work.test;
17 | file inc;
18 | libds=cats('sashelp.',memname);
19 | if exist(libds) then line=cats('%mp_ds2fmtds(',libds,',',memname,')');
20 | put line;
21 | run;
22 |
23 | options obs=50;
24 | %inc inc;
25 |
26 | %mp_assert(
27 | iftrue=(&syscc=0),
28 | desc=Checking tables were created successfully,
29 | outds=work.test_results
30 | )
--------------------------------------------------------------------------------
/tests/base/mp_ds2inserts.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_ds2inserts.sas macro
4 |
5 | SAS Macros
6 | @li mp_ds2inserts.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | /**
12 | * test 1 - rebuild an existing dataset
13 | * Cars is a great dataset - it contains leading spaces, and formatted numerics
14 | */
15 |
16 | %mp_ds2inserts(sashelp.cars,outref=testref,schema=work,outds=test)
17 |
18 | data work.test;
19 | set sashelp.cars;
20 | stop;
21 | proc sql;
22 | %inc testref;
23 |
24 | proc compare base=sashelp.cars compare=work.test;
25 | quit;
26 |
27 | %mp_assert(
28 | iftrue=(&sysinfo=1),
29 | desc=sashelp.cars is identical except for ds label,
30 | outds=work.test_results
31 | )
--------------------------------------------------------------------------------
/tests/base/mp_ds2md.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_ds2md.sas macro
4 |
5 | SAS Macros
6 | @li mp_ds2md.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | %mp_ds2md(sashelp.class,outref=md)
12 |
13 | data _null_;
14 | infile md;
15 | input;
16 | call symputx(cats('test',_n_),_infile_);
17 | if _n_=4 then stop;
18 | run;
19 |
20 | %mp_assert(
21 | iftrue=("&test1"="|NAME:$8.|SEX:$1.|AGE:best.|HEIGHT:best.|WEIGHT:best.|"),
22 | desc=Checking header row,
23 | outds=work.test_results
24 | )
25 | %mp_assert(
26 | iftrue=("&test2"="|---|---|---|---|---|"),
27 | desc=Checking divider row,
28 | outds=work.test_results
29 | )
30 | %mp_assert(
31 | iftrue=("&test3"="|`Alfred `|`M `|`14 `|`69 `|`112.5 `|"),
32 | desc=Checking data row,
33 | outds=work.test_results
34 | )
--------------------------------------------------------------------------------
/tests/base/mp_ds2squeeze.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_ds2squeeze.sas macro
4 |
5 | SAS Macros
6 | @li mf_getvarlen.sas
7 | @li mp_assert.sas
8 | @li mp_assertscope.sas
9 | @li mp_ds2squeeze.sas
10 |
11 | **/
12 |
13 | data big;
14 | length my big $32000;
15 | do i=1 to 1e4;
16 | my=repeat('oh my',100);
17 | big='dawg';
18 | special=._;
19 | missn=.;
20 | missc='';
21 | output;
22 | end;
23 | run;
24 |
25 | %mp_assertscope(SNAPSHOT)
26 | %mp_ds2squeeze(work.big,outds=work.smaller)
27 | %mp_assertscope(COMPARE)
28 |
29 | %mp_assert(
30 | iftrue=(&syscc=0),
31 | desc=Checking syscc
32 | )
33 | %mp_assert(
34 | iftrue=(%mf_getvarlen(work.smaller,missn)=3),
35 | desc=Check missing numeric is 3
36 | )
37 | %mp_assert(
38 | iftrue=(%mf_getvarlen(work.smaller,special)=3),
39 | desc=Check missing special numeric is 3
40 | )
41 | %mp_assert(
42 | iftrue=(%mf_getvarlen(work.smaller,missc)=1),
43 | desc=Check missing char is 1
44 | )
45 |
--------------------------------------------------------------------------------
/tests/base/mp_dsmeta.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_dsmeta.sas macro
4 |
5 | SAS Macros
6 | @li mp_assert.sas
7 | @li mp_assertscope.sas
8 | @li mp_dsmeta.sas
9 |
10 | **/
11 |
12 | data work.Example;
13 | set sashelp.vmacro;
14 | run;
15 |
16 | %mp_assertscope(SNAPSHOT)
17 | %mp_dsmeta(work.example,outds=work.test)
18 | %mp_assertscope(COMPARE)
19 |
20 | proc sql noprint;
21 | select count(*) into: nobs from work.test;
22 | select count(distinct ods_table) into: tnobs from work.test;
23 |
24 | %mp_assert(
25 | iftrue=(&tnobs=2),
26 | desc=Check that both ATTRIBUTES and ENGINEHOST are provided
27 | )
28 | %mp_assert(
29 | iftrue=(&nobs>10),
30 | desc=Check that sufficient details are provided
31 | )
32 |
33 |
--------------------------------------------------------------------------------
/tests/base/mp_getcols.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_getcols macro
4 |
5 | SAS Macros
6 | @li mp_getcols.sas
7 | @li mp_assertcols.sas
8 | @li mp_assertcolvals.sas
9 | @li mp_assertdsobs.sas
10 | @li mp_assertscope.sas
11 |
12 | **/
13 |
14 |
15 | /* make some data */
16 | proc sql;
17 | create table work.src(
18 | SOME_DATETIME float format=datetime19.,
19 | SOME_CHAR char(16),
20 | SOME_NUM num,
21 | SOME_TIME num format=time8.,
22 | SOME_DATE num format=date9.
23 | );
24 |
25 | /* run macro, checking for scope leakage */
26 | %mp_assertscope(SNAPSHOT)
27 | %mp_getcols(work.src,outds=work.info)
28 | %mp_assertscope(COMPARE)
29 |
30 | %mp_assertdsobs(work.info,
31 | desc=Has 5 records,
32 | test=EQUALS 5,
33 | outds=work.test_results
34 | )
35 |
36 | data work.check;
37 | length val $10;
38 | do val='NUMERIC','DATE','CHARACTER','DATETIME','TIME';
39 | output;
40 | end;
41 | run;
42 | %mp_assertcolvals(work.info.ddtype,
43 | checkvals=work.check.val,
44 | desc=All values have a match,
45 | test=ALLVALS
46 | )
47 |
48 | %mp_assertcols(work.info,
49 | cols=name type length varnum format label ddtype fmtname,
50 | test=ALL,
51 | desc=check all columns exist
52 | )
--------------------------------------------------------------------------------
/tests/base/mp_getconstraints.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_getconstraints.sas macro
4 |
5 | SAS Macros
6 | @li mf_nobs.sas
7 | @li mp_getconstraints.sas
8 | @li mp_assert.sas
9 | @li mp_assertscope.sas
10 |
11 | **/
12 |
13 |
14 | %macro conditional();
15 |
16 | %if %sysfunc(exist(sashelp.vcncolu,view))=1 %then %do;
17 | proc sql;
18 | create table work.example(
19 | TX_FROM float format=datetime19.,
20 | DD_TYPE char(16),
21 | DD_SOURCE char(2048),
22 | DD_SHORTDESC char(256),
23 | constraint pk primary key(tx_from, dd_type,dd_source),
24 | constraint unq unique(tx_from, dd_type),
25 | constraint nnn not null(DD_SHORTDESC)
26 | );
27 | %mp_assertscope(SNAPSHOT)
28 | %mp_getconstraints(lib=work,ds=example,outds=work.constraints)
29 | %mp_assertscope(COMPARE)
30 |
31 | %mp_assert(
32 | iftrue=(%mf_nobs(work.constraints)=6),
33 | desc=Output table work.constraints created with correct number of records,
34 | outds=work.test_results
35 | )
36 | %end;
37 | %else %do;
38 | proc sql;
39 | create table work.example(
40 | TX_FROM float format=datetime19.,
41 | DD_TYPE char(16),
42 | DD_SOURCE char(2048),
43 | DD_SHORTDESC char(256)
44 | );
45 | %mp_assertscope(SNAPSHOT)
46 | %mp_getconstraints(lib=work,ds=example,outds=work.constraints)
47 | %mp_assertscope(COMPARE)
48 |
49 | %mp_assert(
50 | iftrue=(%mf_nobs(work.constraints)=0),
51 | desc=Empty table created as constraints not supported,
52 | outds=work.test_results
53 | )
54 | %end;
55 | %mend conditional;
56 |
57 | %conditional()
58 |
--------------------------------------------------------------------------------
/tests/base/mp_getddl.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_getddl.sas macro
4 |
5 | SAS Macros
6 | @li mp_getddl.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | data test(index=(pk=(x y)/unique /nomiss));
12 | x=1;
13 | y='blah';
14 | label x='blah';
15 | run;
16 | proc sql; describe table &syslast;
17 | %mp_getddl(work,test,flavour=tsql,showlog=YES)
18 |
19 | %mp_assert(
20 | iftrue=(&syscc=0),
21 | desc=mp_getddl runs without errors,
22 | outds=work.test_results
23 | )
--------------------------------------------------------------------------------
/tests/base/mp_gitadd.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_gitadd.sas macro
4 |
5 | SAS Macros
6 | @li mf_deletefile.sas
7 | @li mf_writefile.sas
8 | @li mp_gitadd.sas
9 | @li mp_gitstatus.sas
10 | @li mp_assert.sas
11 |
12 | **/
13 |
14 | /* clone the source repo */
15 | %let dir = %sysfunc(pathname(work))/core;
16 | %put source clone rc=%sysfunc(GITFN_CLONE(https://github.com/sasjs/core,&dir));
17 |
18 | /* add a file */
19 | %mf_writefile(&dir/somefile.txt,l1=some content)
20 | /* change a file */
21 | %mf_writefile(&dir/readme.md,l1=new readme)
22 | /* delete a file */
23 | %mf_deletefile(&dir/package.json)
24 |
25 | /* Run git status */
26 | %mp_gitstatus(&dir,outds=work.gitstatus)
27 |
28 | %let test1=0;
29 | proc sql noprint;
30 | select count(*) into: test1 from work.gitstatus where staged='FALSE';
31 |
32 | /* should be three unstaged changes now */
33 | %mp_assert(
34 | iftrue=(&test1=3),
35 | desc=3 changes are ready to add,
36 | outds=work.test_results
37 | )
38 |
39 | /* add them */
40 | %mp_gitadd(&dir,inds=work.gitstatus,mdebug=&sasjs_mdebug)
41 |
42 | /* check status */
43 | %mp_gitstatus(&dir,outds=work.gitstatus2)
44 | %let test2=0;
45 | proc sql noprint;
46 | select count(*) into: test2 from work.gitstatus2 where staged='TRUE';
47 |
48 | /* should be three staged changes now */
49 | %mp_assert(
50 | iftrue=(&test2=3),
51 | desc=3 changes were added,
52 | outds=work.test_results
53 | )
54 |
--------------------------------------------------------------------------------
/tests/base/mp_gitlog.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_gitlog.sas macro
4 |
5 | SAS Macros
6 | @li mf_nobs.sas
7 | @li mp_gitlog.sas
8 | @li mp_assert.sas
9 | @li mp_assertscope.sas
10 |
11 | **/
12 |
13 | /* grab core repo */
14 | %let gitdir=%sysfunc(pathname(work))/core;
15 | %let repo=https://github.com/sasjs/core;
16 | %put source clone rc=%sysfunc(GITFN_CLONE(&repo,&gitdir));
17 |
18 | %mp_assertscope(SNAPSHOT)
19 | %mp_gitlog(&gitdir,outds=work.test1)
20 | %mp_assertscope(COMPARE)
21 |
22 | %mp_assert(
23 | iftrue=(&syscc=0),
24 | desc=Regular test works,
25 | outds=work.test_results
26 | )
27 |
28 | %mp_assert(
29 | iftrue=(%mf_nobs(work.test1)>1000),
30 | desc=output has gt 1000 rows,
31 | outds=work.test_results
32 | )
33 |
--------------------------------------------------------------------------------
/tests/base/mp_gitreleaseinfo.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_gitreleaseinfo.sas macro
4 |
5 | SAS Macros
6 | @li mp_gitreleaseinfo.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 |
12 | %mp_gitreleaseinfo(github,sasjs/core,outlib=mylibref,mdebug=1)
13 |
14 | %mp_assert(
15 | iftrue=(&syscc=0),
16 | desc=mp_gitreleaseinfo runs without errors,
17 | outds=work.test_results
18 | )
19 |
20 | data _null_;
21 | set mylibref.author;
22 | putlog (_all_)(=);
23 | call symputx('author',login);
24 | run;
25 |
26 | %mp_assert(
27 | iftrue=(&author=sasjsbot),
28 | desc=release info extracted successfully,
29 | outds=work.test_results
30 | )
31 |
--------------------------------------------------------------------------------
/tests/base/mp_gitstatus.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_gitstatus.sas macro
4 |
5 | SAS Macros
6 | @li mf_deletefile.sas
7 | @li mf_writefile.sas
8 | @li mp_gitstatus.sas
9 | @li mp_assertdsobs.sas
10 |
11 | **/
12 |
13 | /* clone the source repo */
14 | %let dir = %sysfunc(pathname(work))/core;
15 | %put source clone rc=%sysfunc(GITFN_CLONE(https://github.com/sasjs/core,&dir));
16 |
17 | %mp_gitstatus(&dir,outds=work.gitstatus)
18 |
19 | %mp_assert(
20 | iftrue=(&syscc=0),
21 | desc=Initial mp_gitstatus runs without errors,
22 | outds=work.test_results
23 | )
24 |
25 | /* should be empty as there are no changes yet */
26 | %mp_assertdsobs(work.gitstatus,test=EMPTY)
27 |
28 | /* add a file */
29 | %mf_writefile(&dir/somefile.txt,l1=some content)
30 | /* change a file */
31 | %mf_writefile(&dir/readme.md,l1=new readme)
32 | /* delete a file */
33 | %mf_deletefile(&dir/package.json)
34 |
35 | /* re-run git status */
36 | %mp_gitstatus(&dir,outds=work.gitstatus)
37 |
38 | /* should be three changes now */
39 | %mp_assertdsobs(work.gitstatus,test=EQUALS 3)
40 |
--------------------------------------------------------------------------------
/tests/base/mp_hashdataset.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_hashdataset.sas macro
4 |
5 | SAS Macros
6 | @li mf_nobs.sas
7 | @li mp_hashdataset.sas
8 | @li mp_assert.sas
9 | @li mp_assertscope.sas
10 |
11 | **/
12 |
13 | /* test 1 - regular DS */
14 | data work.test;
15 | set sashelp.vextfl;
16 | missval=.;
17 | misscval='';
18 | run;
19 |
20 | %mp_assertscope(SNAPSHOT)
21 | %mp_hashdataset(test)
22 | %mp_assertscope(COMPARE)
23 |
24 | %mp_assert(
25 | iftrue=(&syscc=0),
26 | desc=Regular test works,
27 | outds=work.test_results
28 | )
29 |
30 | %mp_hashdataset(test,outds=work.test2)
31 |
32 | %mp_assert(
33 | iftrue=(&syscc=0),
34 | desc=hash with output runs without errors,
35 | outds=work.test_results
36 | )
37 |
38 | %mp_assert(
39 | iftrue=(%mf_nobs(work.test2)=1),
40 | desc=output has 1 row,
41 | outds=work.test_results
42 | )
43 |
44 |
45 | data work.test3a;
46 | set work.test;
47 | stop;
48 | run;
49 | %mp_hashdataset(test3a,outds=work.test3b)
50 |
51 | %mp_assert(
52 | iftrue=(&syscc=0),
53 | desc=hash with zero-row input runs without errors,
54 | outds=work.test_results
55 | )
56 |
57 | %mp_assert(
58 | iftrue=(%mf_nobs(work.test3b)=1),
59 | desc=test 3 output has 1 row,
60 | outds=work.test_results
61 | )
62 |
--------------------------------------------------------------------------------
/tests/base/mp_init.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_gsubfile.sas macro
4 |
5 | SAS Macros
6 | @li mp_init.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | /**
12 | * Test 1 - mp_init.sas actually already ran as part of testinit
13 | * So lets test to make sure it will not run again
14 | */
15 |
16 | %let initial_value=&sasjs_init_num;
17 |
18 | %mp_init()
19 |
20 | %mp_assert(
21 | iftrue=("&initial_value"="&sasjs_init_num"),
22 | desc=Check that mp_init() did not run twice,
23 | outds=work.test_results
24 | )
--------------------------------------------------------------------------------
/tests/base/mp_jsonout.test.1.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_jsonout.sas macro
4 |
5 | SAS Macros
6 | @li mp_jsonout.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | filename webref temp;
12 |
13 | data demo;
14 | dtval=date();
15 | format dtval date9.;
16 | compare=put(date(),date9.);
17 | call symputx('compare',compare);
18 | run;
19 |
20 | %mp_jsonout(OPEN,jref=webref)
21 | %mp_jsonout(OBJ,demo,jref=webref,fmt=Y)
22 | %mp_jsonout(CLOSE,jref=webref)
23 |
24 | data _null_;
25 | infile webref;
26 | input;
27 | putlog _infile_;
28 | run;
29 |
30 | libname web JSON fileref=webref;
31 | %let dtval=0;
32 | data work.test;
33 | set web.demo;
34 | call symputx('dtval',dtval);
35 | run;
36 |
37 | %mp_assert(
38 | iftrue=(&syscc=0),
39 | desc=Checking for error condition,
40 | outds=work.test_results
41 | )
42 |
43 | %mp_assert(
44 | iftrue=(&dtval=&compare),
45 | desc=Checking tables were created successfully,
46 | outds=work.test_results
47 | )
--------------------------------------------------------------------------------
/tests/base/mp_jsonout.test.2.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_jsonout.sas macro with special missings
4 |
5 | SAS Macros
6 | @li mp_jsonout.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | filename webref temp;
12 |
13 | data demo;
14 | do x=._,.,.a,.b,.c,.d,.e,-99, 0, 1,2, 3.333333;
15 | output;
16 | end;
17 | run;
18 | %mp_jsonout(OPEN,jref=webref)
19 | %mp_jsonout(OBJ,demo,jref=webref,fmt=N,missing=STRING)
20 | %mp_jsonout(CLOSE,jref=webref)
21 |
22 | data _null_;
23 | infile webref;
24 | input;
25 | putlog _infile_;
26 | run;
27 |
28 | libname web JSON fileref=webref;
29 |
30 | /* proc json turns to char - so switch back to numeric */
31 | data work.test(keep=x);
32 | set web.demo(rename=(x=y));
33 | if y ='_' then x=._;
34 | else if anyalpha(y) then x=input(cats(".",y),best.);
35 | else x=input(y,best.);
36 | put (_all_)(=);
37 | run;
38 |
39 | %mp_assert(
40 | iftrue=(&syscc=0),
41 | desc=Checking for error condition with special missing export,
42 | outds=work.test_results
43 | )
44 |
45 | proc compare base=work.demo compare=work.test;
46 | quit;
47 |
48 | %mp_assert(
49 | iftrue=(&sysinfo=0),
50 | desc=Returned json is identical to input table for all special missings,
51 | outds=work.test_results
52 | )
--------------------------------------------------------------------------------
/tests/base/mp_jsonout.test.3.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_jsonout.sas macro with non-standard chars
4 |
5 | SAS Macros
6 | @li mp_jsonout.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | filename webref temp;
12 |
13 | data demo;
14 | do x='"','0A'x,'0D'x,'09'x,'00'x,'0E'x,'0F'x,'01'x,'02'x,'10'x,'11'x,'\';
15 | output;
16 | end;
17 | run;
18 | %mp_jsonout(OPEN,jref=webref)
19 | %mp_jsonout(OBJ,demo,jref=webref)
20 | %mp_jsonout(CLOSE,jref=webref)
21 |
22 | data _null_;
23 | infile webref;
24 | input;
25 | putlog _infile_;
26 | run;
27 |
28 | libname web JSON fileref=webref;
29 |
30 | %mp_assert(
31 | iftrue=(&syscc=0),
32 | desc=Checking for error condition with special chars export,
33 | outds=work.test_results
34 | )
35 |
36 | /*
37 | data _null_;
38 | set work.demo (in=start) web.demo (in=end);
39 | put (_all_)(=);
40 | run;
41 | proc sql;
42 | describe table work.demo;
43 | describe table web.demo;
44 | */
45 |
46 | proc compare base=work.demo compare=web.demo(keep=x);
47 | quit;
48 |
49 | %mp_assert(
50 | iftrue=(&sysinfo=0),
51 | desc=Returned json is identical to input table for all special chars,
52 | outds=work.test_results
53 | )
54 |
--------------------------------------------------------------------------------
/tests/base/mp_lib2inserts.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_ds2inserts.sas macro
4 |
5 | SAS Macros
6 | @li mf_mkdir.sas
7 | @li mp_getddl.sas
8 | @li mp_lib2inserts.sas
9 | @li mp_assert.sas
10 |
11 | **/
12 |
13 | /* grab 20 datasets from SASHELP */
14 | %let work=%sysfunc(pathname(work));
15 | %let path=&work/new;
16 | %mf_mkdir(&path)
17 | libname sashlp "&work";
18 | proc sql noprint;
19 | create table members as
20 | select distinct lowcase(memname) as memname
21 | from dictionary.tables
22 | where upcase(libname)="SASHELP"
23 | and memtype='DATA'; /* exclude views */
24 | data _null_;
25 | set work.members;
26 | call execute(cats('data sashlp.',memname,';set sashelp.',memname,';run;'));
27 | if _n_>20 then stop;
28 | run;
29 |
30 | /* export DDL and inserts */
31 | %mp_getddl(sashlp, schema=work, fref=tempref)
32 | %mp_lib2inserts(sashlp, schema=work, outref=tempref,maxobs=50)
33 |
34 | /* check if it actually runs */
35 | libname sashlp "&path";
36 | options source2;
37 | %inc tempref;
38 |
39 | /* without errors.. */
40 | %mp_assert(
41 | iftrue=(&syscc=0),
42 | desc=Able to export 20 tables from sashelp using mp_lib2inserts,
43 | outds=work.test_results
44 | )
--------------------------------------------------------------------------------
/tests/base/mp_lockfilecheck.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_lockfilecheck macro
4 |
5 | SAS Macros
6 | @li mp_lockfilecheck.sas
7 | @li mp_assert.sas
8 | @li mp_reseterror.sas
9 |
10 | **/
11 |
12 |
13 | /* check for regular lock */
14 | data work.test; a=1;run;
15 | %mp_lockfilecheck(work.test)
16 |
17 | %mp_assert(
18 | iftrue=(&syscc=0),
19 | desc=Checking regular table can be locked,
20 | outds=work.test_results
21 | )
22 |
23 |
24 | /* check for unsuccessful lock */
25 | %global success abortme;
26 | %let success=0;
27 | %macro mp_abort(iftrue=,mac=,msg=);
28 | %if &abortme=1 %then %let success=1;
29 | %mend mp_abort;
30 |
31 | %mp_lockfilecheck(sashelp.class)
32 |
33 | %mp_reseterror()
34 |
35 | %mp_assert(
36 | iftrue=(&success=1),
37 | desc=Checking sashelp table cannot be locked,
38 | outds=work.test_results
39 | )
40 |
--------------------------------------------------------------------------------
/tests/base/mp_makedata.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_makedata.sas macro
4 |
5 | SAS Macros
6 | @li mf_nobs.sas
7 | @li mp_makedata.sas
8 | @li mp_assert.sas
9 |
10 | **/
11 |
12 | /**
13 | * Test 1 - Regular makedata call
14 | */
15 |
16 | proc sql;
17 | create table work.example(
18 | TX_FROM float format=datetime19.,
19 | DD_TYPE char(16),
20 | DD_SOURCE char(2048),
21 | DD_SHORTDESC char(256),
22 | constraint pk primary key(tx_from, dd_type,dd_source),
23 | constraint nnn not null(DD_SHORTDESC)
24 | );
25 | %mp_makedata(work.example,obs=500)
26 |
27 | %mp_assert(
28 | iftrue=("%mf_nobs(work.example)"="500"),
29 | desc=Check that 500 rows were created,
30 | outds=work.test_results
31 | )
32 |
33 | data _null_;
34 | set work.example;
35 | call symputx('lenvar',length(dd_source));
36 | stop;
37 | run;
38 | %mp_assert(
39 | iftrue=("&lenvar"="2048"),
40 | desc=Check that entire length of variable is populated,
41 | outds=work.test_results
42 | )
43 |
44 |
45 | proc sql;
46 | create table work.example2(
47 | TX_FROM float format=datetime19.,
48 | DD_TYPE char(16),
49 | DD_SOURCE char(2048),
50 | DD_SHORTDESC char(256),
51 | some_num num
52 | );
53 | %mp_makedata(work.example2)
54 |
55 | %mp_assert(
56 | iftrue=(&syscc=0),
57 | desc=Ensure tables without keys still generate,
58 | outds=work.test_results
59 | )
--------------------------------------------------------------------------------
/tests/base/mp_md5.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_md5.sas macro
4 |
5 | SAS Macros
6 | @li mp_md5.sas
7 | @li mp_assert.sas
8 | @li mp_assertscope.sas
9 |
10 | **/
11 | %global hash1 hash2 hash3;
12 |
13 | %mp_assertscope(SNAPSHOT)
14 | data work.test1 /nonote2err;
15 | c1='';
16 | c2=repeat('x',32767);
17 | c3=' f';
18 | n1=.a;
19 | n2=.;
20 | n3=1.0000000001;
21 | hash=%mp_md5(cvars=c1 c2 c3,nvars=n1 n2 n3);
22 | call symputx('hash1',hash);
23 | n1=.b;
24 | hash=%mp_md5(cvars=c1 c2 c3,nvars=n1 n2 n3);
25 | call symputx('hash2',hash);
26 | c3='f';
27 | hash=%mp_md5(cvars=c1 c2 c3,nvars=n1 n2 n3);
28 | call symputx('hash3',hash);
29 | run;
30 | %mp_assertscope(COMPARE,ignorelist=HASH1 HASH2 HASH3)
31 |
32 | %mp_assert(
33 | iftrue=("&hash1" ne "&hash2"),
34 | desc=Checking first hash diff,
35 | outds=work.test_results
36 | )
37 | %mp_assert(
38 | iftrue=("&hash2" ne "&hash3"),
39 | desc=Checking first hash diff,
40 | outds=work.test_results
41 | )
42 |
--------------------------------------------------------------------------------
/tests/base/mp_reseterror.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_reseterror macro
4 |
5 | SAS Macros
6 | @li mp_assert.sas
7 | @li mp_reseterror.sas
8 |
9 | **/
10 |
11 |
12 | /* cause an error */
13 |
14 | lock sashelp.class;
15 |
16 | /* recover ? */
17 | %mp_reseterror()
18 |
19 | %mp_assert(
20 | iftrue=(&syscc=0),
21 | desc=Checking error condition was fixed,
22 | outds=work.test_results
23 | )
24 |
--------------------------------------------------------------------------------
/tests/base/mp_resetoption.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_resetoption macro
4 |
5 | SAS Macros
6 | @li mp_assert.sas
7 | @li mp_assertscope.sas
8 | @li mp_resetoption.sas
9 |
10 | **/
11 |
12 |
13 | %let orig=%sysfunc(getoption(obs));
14 |
15 | options obs=30;
16 |
17 | %mp_assertscope(SNAPSHOT)
18 | %mp_resetoption(OBS)
19 | %mp_assertscope(COMPARE)
20 |
21 | %let new=%sysfunc(ifc(
22 | "%substr(&sysver,1,1)" ne "4" and "%substr(&sysver,1,1)" ne "5",
23 | %sysfunc(getoption(obs)), /* test it worked */
24 | &orig /* cannot test as option unavailable */
25 | ));
26 |
27 | %mp_assert(
28 | iftrue=(&new=&orig),
29 | desc=Checking option was reset (if reset option available),
30 | outds=work.test_results
31 | )
32 |
--------------------------------------------------------------------------------
/tests/base/mp_searchcols.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_searchcols.sas
4 |
5 | SAS Macros
6 | @li mp_searchcols.sas
7 | @li mp_assertdsobs.sas
8 |
9 |
10 | **/
11 |
12 |
13 | /** Test 1 - full col match */
14 | data example1;
15 | var1=1;
16 | var2=2;
17 | var3=3;
18 | data example2;
19 | var1=1;
20 | var2=2;
21 | data example3;
22 | var2=2;
23 | var3=3;
24 | data example4;
25 | matchmehere=1;
26 | data example5;
27 | hereyoucan_matchme_also=1;
28 | data example6;
29 | do_not_forget_me=1;
30 | data example7;
31 | we_shall_not_forget=1;
32 | run;
33 |
34 | %mp_searchcols(libs=work,cols=var1 var2,outds=testme)
35 |
36 | %mp_assertdsobs(work.testme,
37 | desc=Test1 - check exact variables are found,
38 | test=EQUALS 3,
39 | outds=work.test_results
40 | )
41 |
42 | /* test 2 - wildcard match */
43 |
44 | %mp_searchcols(libs=work,cols=matchme forget,match=WILD, outds=testme2)
45 |
46 | %mp_assertdsobs(work.testme2,
47 | desc=Test1 - check fuzzy matches are found,
48 | test=EQUALS 4,
49 | outds=work.test_results
50 | )
--------------------------------------------------------------------------------
/tests/base/mp_searchdata.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_searchdata.sas
4 |
5 | SAS Macros
6 | @li mp_searchdata.sas
7 | @li mp_assert.sas
8 |
9 |
10 | **/
11 |
12 | /** Test 1 - generic useage */
13 |
14 | %mp_searchdata(lib=sashelp, ds=class, string=a)
15 | %mp_assert(
16 | iftrue=(&syscc=0),
17 | desc=No errors in regular usage,
18 | outds=work.test_results
19 | )
20 |
21 | /** Test 2 - with obs issue */
22 |
23 | %mp_searchdata(lib=sashelp, ds=class, string=l,outobs=5)
24 |
25 | %mp_assert(
26 | iftrue=("&SYSWARNINGTEXT" = ""),
27 | desc=Ensuring WARN status is clean,
28 | outds=work.test_results
29 | )
30 |
--------------------------------------------------------------------------------
/tests/base/mp_sortinplace.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_sortinplace.test.sas
4 |
5 | SAS Macros
6 | @li mp_sortinplace.sas
7 | @li mp_assert.sas
8 | @li mp_assertdsobs.sas
9 | @li mp_getconstraints.sas
10 |
11 | **/
12 |
13 |
14 | /** Test 1 - regular usage */
15 | proc sql;
16 | create table work.example as
17 | select * from sashelp.classfit;
18 | alter table work.example
19 | add constraint pk primary key(name);
20 | %mp_sortinplace(work.example)
21 |
22 | %mp_getconstraints(lib=work,ds=example,outds=work.testme)
23 |
24 | %mp_assertdsobs(work.testme,
25 | desc=Test1 - check constraints recreated,
26 | test=EQUALS 1,
27 | outds=work.test_results
28 | )
29 |
30 | %let test1=0;
31 | data _null_;
32 | set work.example;
33 | call symputx('test1',name);
34 | stop;
35 | run;
36 | %mp_assert(
37 | iftrue=(
38 | %str(&test1)=%str(Alfred)
39 | ),
40 | desc=Check if sort was appplied,
41 | outds=work.test_results
42 | )
43 |
44 | /** Test 2 - table without PK */
45 | proc sql;
46 | create table work.example2 as
47 | select * from sashelp.classfit;
48 | %mp_sortinplace(work.example2)
49 | %mp_assert(
50 | iftrue=(
51 | %str(&syscc)=%str(0)
52 | ),
53 | desc=Ensure no errors when no key exists,
54 | outds=work.test_results
55 | )
56 |
57 | %let test2=0;
58 | data _null_;
59 | set work.example2;
60 | call symputx('test2',name);
61 | stop;
62 | run;
63 | %mp_assert(
64 | iftrue=(
65 | %str(&test2)=%str(Alfred)
66 | ),
67 | desc=Check if sort was appplied when no index exists,
68 | outds=work.test_results
69 | )
--------------------------------------------------------------------------------
/tests/base/mp_streamfile.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_streamfile.sas macro
4 | @details This is tricky to test as it streams to webout. For now just
5 | check the compilation, and for macro leakage.
6 |
7 | SAS Macros
8 | @li mp_assert.sas
9 | @li mp_assertscope.sas
10 | @li mp_streamfile.sas
11 |
12 | **/
13 |
14 | %mp_assertscope(SNAPSHOT)
15 |
16 | %mp_streamfile(iftrue=(1=0)
17 | ,contenttype=csv,inloc=/some/where.txt
18 | ,outname=myfile.txt
19 | )
20 |
21 | %mp_assertscope(COMPARE)
22 |
23 | %mp_assert(
24 | iftrue=(&syscc=0),
25 | desc=Checking error condition,
26 | outds=work.test_results
27 | )
28 |
29 |
--------------------------------------------------------------------------------
/tests/base/mp_webin.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mp_webin macro
4 |
5 | SAS Macros
6 | @li mp_webin.sas
7 | @li mp_assert.sas
8 |
9 | **/
10 |
11 | /* force SAS9 tests as we don't have a valid URI available */
12 | %macro mf_getplatform();
13 | SAS9
14 | %mend mf_getplatform;
15 |
16 | /* TEST 1 */
17 | %let _webin_file_count=1;
18 | %let _webin_filename=test;
19 | %mp_webin()
20 |
21 | %mp_assert(
22 | iftrue=(
23 | %symexist(_WEBIN_FILEREF1)
24 | ),
25 | desc=Checking if the macvar exists,
26 | outds=work.test_results
27 | )
28 |
29 | /* TEST 2 */
30 | %global _WEBIN_FILENAME1;
31 | %mp_assert(
32 | iftrue=(
33 | %str(&_WEBIN_FILENAME1)=%str(test)
34 | ),
35 | desc=Checking if the macvar exists,
36 | outds=work.test_results
37 | )
38 |
39 |
40 |
--------------------------------------------------------------------------------
/tests/ddlonly/mddl_dc_difftable.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Difftable DDL test
4 |
5 | SAS Macros
6 | @li mddl_dc_difftable.sas
7 | @li mf_existds.sas
8 | @li mp_assert.sas
9 |
10 | **/
11 |
12 |
13 | %mddl_dc_difftable(libds=WORK.DIFFTABLE)
14 |
15 | %mp_assert(
16 | iftrue=(%mf_existds(WORK.DIFFTABLE)=1),
17 | desc=Checking table was created,
18 | outds=work.test_results
19 | )
--------------------------------------------------------------------------------
/tests/ddlonly/mddl_dc_filterdetail.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Filtertable DDL test
4 |
5 | SAS Macros
6 | @li mddl_dc_filterdetail.sas
7 | @li mf_existds.sas
8 | @li mp_assert.sas
9 |
10 | **/
11 |
12 | %mddl_dc_filterdetail(libds=WORK.TEST)
13 |
14 | %mp_assert(
15 | iftrue=(%mf_existds(WORK.TEST)=1),
16 | desc=Checking table was created,
17 | outds=work.test_results
18 | )
--------------------------------------------------------------------------------
/tests/ddlonly/mddl_dc_filtersummary.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Filtersummary DDL test
4 |
5 | SAS Macros
6 | @li mddl_dc_filtersummary.sas
7 | @li mf_existds.sas
8 | @li mp_assert.sas
9 |
10 | **/
11 |
12 | %mddl_dc_filtersummary(libds=WORK.TEST)
13 |
14 | %mp_assert(
15 | iftrue=(%mf_existds(WORK.TEST)=1),
16 | desc=Checking table was created,
17 | outds=work.test_results
18 | )
--------------------------------------------------------------------------------
/tests/ddlonly/mddl_dc_locktable.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Locktable DDL test
4 |
5 | SAS Macros
6 | @li mddl_dc_locktable.sas
7 | @li mf_existds.sas
8 | @li mp_assert.sas
9 |
10 | **/
11 |
12 | %mddl_dc_locktable(libds=WORK.TEST)
13 |
14 | %mp_assert(
15 | iftrue=(%mf_existds(WORK.TEST)=1),
16 | desc=Checking table was created,
17 | outds=work.test_results
18 | )
--------------------------------------------------------------------------------
/tests/ddlonly/mddl_dc_maxkeytable.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Maxkeytable DDL test
4 |
5 | SAS Macros
6 | @li mddl_dc_maxkeytable.sas
7 | @li mf_existds.sas
8 | @li mp_assert.sas
9 |
10 | **/
11 |
12 | %mddl_dc_maxkeytable(libds=WORK.TEST)
13 |
14 | %mp_assert(
15 | iftrue=(%mf_existds(WORK.TEST)=1),
16 | desc=Checking table was created,
17 | outds=work.test_results
18 | )
--------------------------------------------------------------------------------
/tests/ddlonly/mddl_sas_cntlout.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief mddl_sas_cntlout ddl test
4 |
5 | SAS Macros
6 | @li mddl_sas_cntlout.sas
7 | @li mf_existds.sas
8 | @li mp_assert.sas
9 |
10 | **/
11 |
12 | %mddl_sas_cntlout(libds=WORK.TEST)
13 |
14 | %mp_assert(
15 | iftrue=(%mf_existds(WORK.TEST)=1),
16 | desc=Checking table was created,
17 | outds=work.test_results
18 | )
--------------------------------------------------------------------------------
/tests/sas9only/mm_getauthinfo.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mm_getauthinfo macro
4 |
5 | SAS Macros
6 | @li mf_existds.sas
7 | @li mm_getauthinfo.sas
8 | @li mp_assertscope.sas
9 |
10 | **/
11 |
12 |
13 | %mp_assertscope(SNAPSHOT)
14 | %mm_getauthinfo(outds=auths)
15 | %mp_assertscope(COMPARE)
16 |
17 |
18 | %mp_assert(
19 | iftrue=(%mf_existds(work.auths)=1),
20 | desc=Check if the auths dataset was created
21 | )
--------------------------------------------------------------------------------
/tests/sas9only/mm_spkexport.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mm_webout macro
4 |
5 | SAS Macros
6 | @li mm_spkexport.sas
7 | @li mp_assert.sas
8 | @li mp_as
9 |
10 | **/
11 |
12 |
13 | %* create sample text file as input to the macro;
14 | filename tmp temp;
15 | data _null_;
16 | file tmp;
17 | put '%let mmxuser="sasdemo";';
18 | put '%let mmxpass="Mars321";';
19 | run;
20 |
21 | filename myref "%sysfunc(pathname(work))/mmxexport.sh"
22 | permission='A::u::rwx,A::g::r-x,A::o::---';
23 | %mp_assertscope(SNAPSHOT)
24 | %mm_spkexport(metaloc=%str(/Shared Data)
25 | ,outref=myref
26 | ,secureref=tmp
27 | ,cmdoutloc=%str(/tmp)
28 | )
29 | %mp_assertscope(COMPARE)
30 |
31 | data _null_;
32 | infile tmp;
33 | input;
34 | putlog _infile_;
35 | call symputx('nobs',_n_);
36 | run;
37 |
38 | %mp_assert(
39 | iftrue=(&nobs>2),
40 | desc=Check if content was created
41 | )
42 |
--------------------------------------------------------------------------------
/tests/sas9only/mm_webout.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mm_webout macro
4 |
5 | SAS Macros
6 | @li mf_getuniquefileref.sas
7 | @li mm_webout.sas
8 | @li mp_assert.sas
9 |
10 | **/
11 |
12 |
13 | %let fref=%mf_getuniquefileref();
14 | %global _metaperson;
15 | data some datasets;
16 | x=1;
17 | run;
18 | %mm_webout(OPEN,fref=&fref)
19 | %mm_webout(ARR,some,fref=&fref)
20 | %mm_webout(OBJ,datasets,fref=&fref)
21 | %mm_webout(CLOSE,fref=&fref)
22 |
23 | libname test JSON (&fref);
24 | data root;
25 | set test.root;
26 | call symputx('checkval',sysvlong);
27 | run;
28 | data alldata;
29 | set test.alldata;
30 | run;
31 |
32 | %mp_assert(
33 | iftrue=(%str(&checkval)=%str(&sysvlong)),
34 | desc=Check if the sysvlong value was created
35 | )
--------------------------------------------------------------------------------
/tests/serveronly/mfs_httpheader.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mfs_httpheader.sas macro
4 |
5 | SAS Macros
6 | @li mfs_httpheader.sas
7 | @li mp_assert.sas
8 | @li mp_assertscope.sas
9 |
10 | **/
11 |
12 | %let orig_sasjs_stpsrv_header_loc=&sasjs_stpsrv_header_loc;
13 | %let sasjs_stpsrv_header_loc=%sysfunc(pathname(work))/header.txt;
14 |
15 | %mp_assertscope(SNAPSHOT)
16 | %mfs_httpheader(Content-Type,application/csv)
17 | %mp_assertscope(COMPARE,ignorelist=sasjs_stpsrv_header_loc)
18 |
19 | data _null_;
20 | infile "&sasjs_stpsrv_header_loc";
21 | input;
22 | if _n_=1 then call symputx('test1',_infile_);
23 | run;
24 |
25 | %mp_assert(
26 | iftrue=(&syscc=0),
27 | desc=Check code ran without errors,
28 | outds=work.test_results
29 | )
30 | %mp_assert(
31 | iftrue=("&test1"="Content-Type: application/csv"),
32 | desc=Checking line was created,
33 | outds=work.test_results
34 | )
35 |
36 | %mfs_httpheader(Content-Type,application/text)
37 | %let test2=0;
38 | data _null_;
39 | infile "&sasjs_stpsrv_header_loc";
40 | input;
41 | if _n_=2 then call symputx('test2',_infile_);
42 | run;
43 |
44 | %mp_assert(
45 | iftrue=(&syscc=0),
46 | desc=Check code ran without errors for test2,
47 | outds=work.test_results
48 | )
49 | %mp_assert(
50 | iftrue=("&test2"="Content-Type: application/text"),
51 | desc=Checking line was created,
52 | outds=work.test_results
53 | )
54 |
55 |
56 | /* reset header so the test will pass */
57 | %let sasjs_stpsrv_header_loc=&orig_sasjs_stpsrv_header_loc;
--------------------------------------------------------------------------------
/tests/serveronly/ms_adduser2group.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing ms_adduser2group.sas macro
4 |
5 | SAS Macros
6 | @li mf_getuniquename.sas
7 | @li mp_assert.sas
8 | @li mp_assertscope.sas
9 | @li ms_adduser2group.sas
10 | @li ms_creategroup.sas
11 |
12 | **/
13 |
14 | /* first, create an empty group */
15 | %let group=%substr(%mf_getuniquename(),1,8);
16 | %ms_creategroup(&group, desc=The description,mdebug=&sasjs_mdebug,outds=test1a)
17 | %let groupid=0;
18 | data _null_;
19 | set work.test1a;
20 | call symputx('groupid',groupid);
21 | run;
22 | %mp_assert(
23 | iftrue=(&groupid>0),
24 | desc=Checking that group was created with an ID,
25 | outds=work.test_results
26 | )
27 |
28 | /* now add a user (user 1 always exists) */
29 |
30 |
31 | %mp_assertscope(SNAPSHOT)
32 | %ms_adduser2group(uid=1,gid=&groupid,mdebug=&sasjs_mdebug,outds=test1)
33 | %mp_assertscope(COMPARE
34 | ,ignorelist=MCLIB2_JADP1LEN MCLIB2_JADP2LEN MCLIB2_JADPNUM MCLIB2_JADVLEN
35 | )
36 |
37 | /* check the user is in the output list */
38 | %let checkid=0;
39 | data _null_;
40 | set work.test1;
41 | if id=1 then call symputx('checkid',1);
42 | run;
43 | %mp_assert(
44 | iftrue=(&checkid=1),
45 | desc=Checking that user was created in the new group,
46 | outds=work.test_results
47 | )
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/tests/serveronly/ms_createfile.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing ms_createfile.sas macro
4 |
5 | SAS Macros
6 | @li ms_createfile.sas
7 | @li mp_assert.sas
8 | @li mp_assertscope.sas
9 |
10 | **/
11 |
12 |
13 | filename stpcode temp;
14 | data _null_;
15 | file stpcode;
16 | put '%put hello world;';
17 | run;
18 |
19 | options mprint;
20 | %let fname=%mf_getuniquename();
21 |
22 | %mp_assertscope(SNAPSHOT)
23 | %ms_createfile(/sasjs/tests/&fname..sas
24 | ,inref=stpcode
25 | ,mdebug=1
26 | )
27 | %mp_assertscope(COMPARE)
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/tests/serveronly/ms_creategroup.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing ms_creategroup.sas macro
4 |
5 | SAS Macros
6 | @li mf_getuniquename.sas
7 | @li mp_assert.sas
8 | @li mp_assertscope.sas
9 | @li ms_creategroup.sas
10 | @li ms_getgroups.sas
11 |
12 | **/
13 |
14 | %let group=%substr(%mf_getuniquename(),1,8);
15 |
16 | %mp_assertscope(SNAPSHOT)
17 | %ms_creategroup(&group, desc=The description,mdebug=&sasjs_mdebug,outds=test1)
18 | %mp_assertscope(COMPARE
19 | ,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADPNUM MCLIB0_JADVLEN
20 | )
21 |
22 | %let id=0;
23 | data _null_;
24 | set work.test1;
25 | call symputx('id',groupid);
26 | run;
27 | %mp_assert(
28 | iftrue=(&id>0),
29 | desc=Checking that group was created with an ID,
30 | outds=work.test_results
31 | )
32 |
33 | /* double check by querying the list of users */
34 | %ms_getgroups(outds=work.test2)
35 | %let checkid=0;
36 | data _null_;
37 | set work.test2;
38 | where upcase(name)="%upcase(&group)";
39 | call symputx('checkid',groupid);
40 | run;
41 | %mp_assert(
42 | iftrue=(&checkid=&id),
43 | desc=Checking that fetched group exists and has the same ID,
44 | outds=work.test_results
45 | )
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/tests/serveronly/ms_createuser.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing ms_createuser.sas macro
4 |
5 | SAS Macros
6 | @li mf_getuniquename.sas
7 | @li mp_assert.sas
8 | @li mp_assertscope.sas
9 | @li ms_createuser.sas
10 | @li ms_getusers.sas
11 |
12 | **/
13 |
14 | %let user=%substr(%mf_getuniquename(),1,8);
15 |
16 | %mp_assertscope(SNAPSHOT)
17 | %ms_createuser(&user,passwrd,outds=test1,mdebug=&sasjs_mdebug)
18 | %mp_assertscope(COMPARE
19 | ,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADPNUM MCLIB0_JADVLEN
20 | )
21 |
22 | %let id=0;
23 | data _null_;
24 | set work.test1;
25 | call symputx('id',id);
26 | putlog (_all_)(=);
27 | run;
28 | %mp_assert(
29 | iftrue=(&id>0),
30 | desc=Checking that user was created with an ID,
31 | outds=work.test_results
32 | )
33 |
34 | /* double check by querying the list of users */
35 | %ms_getusers(outds=work.test2)
36 | %let checkid=0;
37 | data _null_;
38 | set work.test2;
39 | if _n_<20 then putlog (_all_)(=);
40 | if upcase(username)="%upcase(&user)";
41 | call symputx('checkid',id);
42 | run;
43 | %mp_assert(
44 | iftrue=(&checkid=&id),
45 | desc=Checking that fetched user exists and has the same ID,
46 | outds=work.test_results
47 | )
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/tests/serveronly/ms_createwebservice.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing ms_createwebservice.sas macro
4 |
5 | SAS Macros
6 | @li mf_getuniquefileref.sas
7 | @li mp_assertscope.sas
8 | @li ms_createwebservice.sas
9 |
10 | **/
11 |
12 | %let path=&mcTestAppLoc/ms_createwebservice;
13 | %let name=myservice;
14 | %let fref=%mf_getuniquefileref();
15 |
16 | data _null_;
17 | file &fref lrecl=3000;
18 | put '%put hello world;';
19 | run;
20 |
21 | %mp_assertscope(SNAPSHOT)
22 | %ms_createwebservice(path=&path,name=&name,code=&fref,mdebug=&sasjs_mdebug)
23 | %mp_assertscope(COMPARE)
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/tests/serveronly/ms_deletefile.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing ms_deletefile.sas macro
4 |
5 | SAS Macros
6 | @li ms_createfile.sas
7 | @li ms_deletefile.sas
8 | @li ms_getfile.sas
9 | @li mp_assert.sas
10 | @li mp_assertscope.sas
11 |
12 | **/
13 |
14 |
15 | /* first make a remote file */
16 | filename stpcode temp;
17 | %let fname=%mf_getuniquename();
18 | data _null_;
19 | file stpcode;
20 | put "data &fname;run;";
21 | run;
22 | %ms_createfile(/sasjs/tests/&fname..sas
23 | ,inref=stpcode
24 | ,mdebug=1
25 | )
26 |
27 | %ms_getfile(/sasjs/tests/&fname..sas,outref=testref)
28 |
29 | %let test1=0;
30 | data _null_;
31 | infile testref;
32 | input;
33 | call symputx('test1',_infile_);
34 | run;
35 |
36 | %mp_assert(
37 | iftrue=("&test1"="data &fname;run;"),
38 | desc=Make sure the file was created,
39 | outds=work.test_results
40 | )
41 |
42 | %mp_assertscope(SNAPSHOT)
43 | %ms_deletefile(/sasjs/tests/&fname..sas,mdebug=1)
44 | %mp_assertscope(COMPARE)
45 |
46 | %ms_getfile(/sasjs/tests/&fname..sas,outref=testref2)
47 |
48 | %let test2=0;
49 | data _null_;
50 | infile testref2;
51 | input;
52 | call symputx('test2',_infile_);
53 | run;
54 |
55 | %mp_assert(
56 | iftrue=("&test2"="File doesn't exist."),
57 | desc=Make sure the file was deleted,
58 | outds=work.test_results
59 | )
60 |
61 |
62 |
--------------------------------------------------------------------------------
/tests/serveronly/ms_getfile.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing ms_getfile.sas macro
4 |
5 | SAS Macros
6 | @li ms_createfile.sas
7 | @li ms_getfile.sas
8 | @li mp_assert.sas
9 | @li mp_assertscope.sas
10 |
11 | **/
12 |
13 |
14 | /* first make a remote file */
15 | filename stpcode temp;
16 | %let fname=%mf_getuniquename();
17 | data _null_;
18 | file stpcode;
19 | put "data &fname;run;";
20 | run;
21 | %ms_createfile(/sasjs/tests/&fname..sas
22 | ,inref=stpcode
23 | ,mdebug=1
24 | )
25 |
26 | %mp_assertscope(SNAPSHOT)
27 | %ms_getfile(/sasjs/tests/&fname..sas,outref=testref)
28 | %mp_assertscope(COMPARE)
29 |
30 | %let test1=0;
31 | data _null_;
32 | infile testref;
33 | input;
34 | call symputx('test1',_infile_);
35 | run;
36 |
37 | %mp_assert(
38 | iftrue=("&test1"="data &fname;run;"),
39 | desc=Checking file was created with the same content,
40 | outds=work.test_results
41 | )
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/tests/serveronly/ms_getusers.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing ms_getusers.sas macro
4 |
5 | SAS Macros
6 | @li ms_creategroup.sas
7 | @li ms_adduser2group.sas
8 | @li ms_getusers.sas
9 | @li mp_assertdsobs.sas
10 | @li mp_assertscope.sas
11 |
12 | **/
13 |
14 |
15 | %mp_assertscope(SNAPSHOT)
16 | %ms_getusers(outds=work.test1,mdebug=&sasjs_mdebug)
17 | %mp_assertscope(COMPARE
18 | ,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADPNUM MCLIB0_JADVLEN
19 | )
20 |
21 | %mp_assertdsobs(work.test1,test=ATLEAST 1)
22 |
23 | /**
24 | * test the extraction of group members
25 | */
26 |
27 | /* create a group */
28 | %let group=%substr(%mf_getuniquename(),1,8);
29 | %ms_creategroup(&group, desc=some desc,mdebug=&sasjs_mdebug,outds=work.group)
30 | %let gid=0;
31 | data _null_;
32 | set work.group;
33 | call symputx('gid',groupid);
34 | run;
35 |
36 | /* add a member */
37 | %ms_adduser2group(uid=1,gid=&gid)
38 |
39 | /* extract the members */
40 | %ms_getusers(group=&group,outds=test2)
41 |
42 | /* check the user is in the output list */
43 | %let checkid=0;
44 | data _null_;
45 | set work.test2;
46 | if id=1 then call symputx('checkid',1);
47 | run;
48 | %mp_assert(
49 | iftrue=(&checkid=1),
50 | desc=Checking that admin user was created in the new group,
51 | outds=work.test_results
52 | )
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/tests/serveronly/ms_runstp.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing ms_runstp.sas macro
4 |
5 | SAS Macros
6 | @li mf_getuniquename.sas
7 | @li mp_assert.sas
8 | @li mp_assertscope.sas
9 | @li ms_createfile.sas
10 | @li ms_runstp.sas
11 |
12 | **/
13 |
14 | /* first, create an STP to run */
15 | filename stpcode temp;
16 | data _null_;
17 | file stpcode;
18 | put '%put hello world;';
19 | put '%put _all_;';
20 | put 'data _null_; file _webout; put "runstptest";run;';
21 | run;
22 |
23 | options mprint;
24 | %let fname=%mf_getuniquename();
25 |
26 | %ms_createfile(/sasjs/tests/&fname..sas
27 | ,inref=stpcode
28 | ,mdebug=1
29 | )
30 |
31 | %mp_assertscope(SNAPSHOT)
32 | %ms_runstp(/sasjs/tests/&fname
33 | ,debug=131
34 | ,outref=weboot
35 | )
36 | %mp_assertscope(COMPARE)
37 |
38 | %let test1=0;
39 | %let test2=0;
40 | data _null_;
41 | infile weboot;
42 | input;
43 | if _n_=1 then call symputx('test1',_infile_);
44 | if _n_=3 then do;
45 | call symputx('test2',substr(_infile_,1,30));
46 | putlog "SASJS_LOGS_SEPARATOR_xxx"; /* this marker affects the CLI parser */
47 | end;
48 | else putlog _infile_;
49 | run;
50 |
51 |
52 |
53 | %mp_assert(
54 | iftrue=("&test1"="runstptest"),
55 | desc=Checking webout was created,
56 | outds=work.test_results
57 | )
58 |
59 | %mp_assert(
60 | iftrue=("&test2"="SASJS_LOGS_SEPARATOR_163ee17b6"),
61 | desc=Checking debug was enabled,
62 | outds=work.test_results
63 | )
64 |
--------------------------------------------------------------------------------
/tests/serveronly/ms_webout.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing ms_webout macro
4 |
5 | SAS Macros
6 | @li mf_getuniquefileref.sas
7 | @li ms_webout.sas
8 | @li mp_assert.sas
9 |
10 | **/
11 |
12 |
13 | %let fref=%mf_getuniquefileref();
14 | %global _metaperson;
15 | data some datasets;
16 | x=1;
17 | run;
18 | %ms_webout(OPEN,fref=&fref)
19 | %ms_webout(ARR,some,fref=&fref)
20 | %ms_webout(OBJ,datasets,fref=&fref)
21 | %ms_webout(CLOSE,fref=&fref)
22 |
23 | libname test JSON fileref=&fref;
24 | data root;
25 | set test.root;
26 | call symputx('checkval',sysvlong);
27 | run;
28 | data alldata;
29 | set test.alldata;
30 | run;
31 |
32 | %mp_assert(
33 | iftrue=(%str(&checkval)=%str(&sysvlong)),
34 | desc=Check if the sysvlong value was created
35 | )
--------------------------------------------------------------------------------
/tests/testinit.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief init file for tests
4 |
5 | SAS Macros
6 | @li mf_uid.sas
7 | @li mp_init.sas
8 | @li ms_webout.sas
9 |
10 | **/
11 |
12 | /* location in metadata or SAS Drive for temporary files */
13 | %let mcTestAppLoc=/Public/testresults/sasjs_core/%mf_uid();
14 |
15 | /* set defaults */
16 | %mp_init()
17 |
18 | options lrecl=80;
19 |
20 | %global _debug sasjs_mdebug;
21 |
22 | %let sasjs_mdebug=0;
23 |
24 | %macro loglevel();
25 | %if "&_debug"="2477" or "&_debug"="fields,log,trace" or "&_debug"="131"
26 | %then %do;
27 | %put debug mode activated;
28 | options mprint mprintnest;
29 | %let sasjs_mdebug=1;
30 | %end;
31 | %mend loglevel;
32 |
33 | %loglevel()
34 |
35 | %put Initialised &_program;
36 | %put _all_;
37 |
--------------------------------------------------------------------------------
/tests/testterm.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief term file for tests
4 |
5 | SAS Macros
6 | @li mp_assert.sas
7 |
8 | **/
9 |
10 | %mp_assert(
11 | iftrue=(&syscc=0),
12 | desc=Checking final err condition,
13 | outds=work.test_results
14 | )
15 |
16 |
17 | %webout(OPEN)
18 | %webout(OBJ, TEST_RESULTS)
19 | %webout(CLOSE)
--------------------------------------------------------------------------------
/tests/viyaonly/mfv_existfile.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mfv_existfile macro function
4 |
5 | SAS Macros
6 | @li mf_uid.sas
7 | @li mfv_existfile.sas
8 | @li mp_assert.sas
9 | @li mv_createfile.sas
10 |
11 | **/
12 |
13 | options mprint sgen;
14 |
15 | %let file=%mf_uid();
16 |
17 | /* create a folder */
18 | filename somefile temp;
19 | data _null_;
20 | file somefile;
21 | put 'hello testings';
22 | run;
23 | %mv_createfile(path=&mcTestAppLoc/temp, name=&file..txt,inref=somefile)
24 |
25 |
26 | %mp_assert(
27 | iftrue=(%mfv_existfile(&mcTestAppLoc/temp/&file..txt)=1),
28 | desc=Check if created file exists
29 | )
30 |
31 | %mp_assert(
32 | iftrue=(%mfv_existfile(&mcTestAppLoc/temp/%mf_uid().txt)=0),
33 | desc=Check if non created file does not exist
34 | )
--------------------------------------------------------------------------------
/tests/viyaonly/mfv_existfolder.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mfv_existfolder macro function
4 |
5 | SAS Macros
6 | @li mf_uid.sas
7 | @li mfv_existfolder.sas
8 | @li mp_assert.sas
9 | @li mv_createfolder.sas
10 |
11 | **/
12 |
13 | options mprint sgen;
14 |
15 | %let folder=%mf_uid();
16 |
17 | /* create a folder */
18 | %mv_createfolder(path=&mcTestAppLoc/temp/&folder)
19 |
20 |
21 | %mp_assert(
22 | iftrue=(%mfv_existfolder(&mcTestAppLoc/temp/&folder)=1),
23 | desc=Check if created folder exists
24 | )
25 |
26 | %mp_assert(
27 | iftrue=(%mfv_existfolder(&mcTestAppLoc/temp/&folder/%mf_uid()/noway)=0),
28 | desc=Check if non created folder does not exist
29 | )
--------------------------------------------------------------------------------
/tests/viyaonly/mfv_getfolderpath.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mfv_getfolderpath macro function
4 |
5 | SAS Macros
6 | @li mf_uid.sas
7 | @li mfv_getfolderpath.sas
8 | @li mfv_getpathuri.sas
9 | @li mp_assert.sas
10 | @li mv_createfolder.sas
11 |
12 | **/
13 |
14 | options mprint sgen;
15 |
16 | %let folder=%mf_uid();
17 | /* create a folder */
18 | %mv_createfolder(path=&mcTestAppLoc/&folder)
19 | %mp_assert(
20 | iftrue=(&syscc=0),
21 | desc=no errs on folder creation
22 | )
23 |
24 | %let uri=%mfv_getpathuri(&mcTestAppLoc/&folder);
25 | %put %mfv_getfolderpath(&uri);
26 |
27 | %mp_assert(
28 | iftrue=("%mfv_getfolderpath(&uri)"="&mcTestAppLoc/&folder"),
29 | desc=Check if correct folder was returned
30 | )
31 |
32 |
--------------------------------------------------------------------------------
/tests/viyaonly/mfv_getpathuri.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mfv_getpathuri macro function
4 |
5 | SAS Macros
6 | @li mf_uid.sas
7 | @li mfv_getpathuri.sas
8 | @li mp_assert.sas
9 | @li mv_createfile.sas
10 |
11 | **/
12 |
13 | options mprint sgen;
14 |
15 | %let file=%mf_uid();
16 |
17 | /* create a file */
18 | filename somefile temp;
19 | data _null_;
20 | file somefile;
21 | put 'hello testings';
22 | run;
23 | %let path=&mcTestAppLoc/temp;
24 | %mv_createfile(path=&path, name=&file..txt,inref=somefile)
25 |
26 |
27 | %mp_assert(
28 | iftrue=(%mfv_existfile(&path/&file..txt)=1),
29 | desc=Check if created file exists
30 | )
31 |
32 | %mp_assert(
33 | iftrue=(%length(%mfv_getpathuri(&path/&file..txt))>0),
34 | desc=Check that a URI was returned
35 | )
--------------------------------------------------------------------------------
/tests/viyaonly/mv_createfolder.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mv_createfolder macro
4 |
5 | SAS Macros
6 | @li mf_uid.sas
7 | @li mp_assert.sas
8 | @li mv_createfolder.sas
9 | @li mv_deleteviyafolder.sas
10 | @li mv_getfoldermembers.sas
11 |
12 | **/
13 |
14 |
15 | %let folder=%mf_uid();
16 |
17 | /* create a folder */
18 | %mv_createfolder(path=&mcTestAppLoc/temp/&folder/&folder)
19 |
20 | %mv_getfoldermembers(root=&mcTestAppLoc/temp/&folder, outds=work.folders)
21 |
22 | %let test=0;
23 | data _null_;
24 | set work.folders;
25 | putlog (_all_)(=);
26 | if name="&folder" then call symputx('test',1);
27 | run;
28 |
29 | %mp_assert(
30 | iftrue=(&test=1),
31 | desc=Check if temp folder can be successfully created
32 | )
33 |
34 | /* create a folder without output dataset as part of the original macro */
35 | %mv_createfolder(path=&mcTestAppLoc/temp/&folder/folder2,outds=folders2)
36 |
37 | %let test=0;
38 | data _null_;
39 | set work.folders2;
40 | putlog (_all_)(=);
41 | if not missing(self_uri) and not missing(parent_uri)
42 | then call symputx('test2',1);
43 | run;
44 |
45 | %mp_assert(
46 | iftrue=(&test2=1),
47 | desc=Check if outds param works
48 | )
--------------------------------------------------------------------------------
/tests/viyaonly/mv_createwebservice.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mv_createwebservice macro
4 |
5 | SAS Macros
6 | @li mv_createwebservice.sas
7 | @li mv_getjobcode.sas
8 |
9 | **/
10 |
11 | /**
12 | * Test Case 1
13 | * Send special char in a service
14 | */
15 |
16 | filename testref temp;
17 | data _null_;
18 | file testref;
19 | put '01'x;
20 | run;
21 | %put TEST1: creating web service;
22 | %mv_createwebservice(
23 | path=&mcTestAppLoc/temp/macros,
24 | name=mv_createwebservice,
25 | code=testref
26 | )
27 | %put TEST1: fetching web service code;
28 | %mv_getjobcode(
29 | path=&mcTestAppLoc/temp/macros,
30 | name=mv_createwebservice,
31 | outref=compare
32 | )
33 | %put TEST1: checking web service code;
34 | data work.test_results;
35 | length test_description $256 test_result $4 test_comments $256;
36 | if _n_=1 then call missing (of _all_);
37 | infile compare end=eof;
38 | input;
39 | if eof then do;
40 | if _infile_='01'x then test_result='PASS';
41 | else test_result='FAIL';
42 | test_description="Creating web service with invisible character";
43 | output;
44 | stop;
45 | end;
46 | run;
--------------------------------------------------------------------------------
/tests/viyaonly/mv_deleteviyafolder.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mv_deleteviyafolder macro function
4 |
5 | SAS Macros
6 | @li mf_uid.sas
7 | @li mfv_existfolder.sas
8 | @li mp_assert.sas
9 | @li mp_assertscope.sas
10 | @li mv_createfolder.sas
11 | @li mv_deleteviyafolder.sas
12 |
13 | **/
14 |
15 | options mprint sgen;
16 |
17 | %let folder=%mf_uid();
18 | %let tgtfolder=&mcTestAppLoc/temp/&folder;
19 |
20 | /* create a folder */
21 | %mv_createfolder(path=&tgtfolder)
22 |
23 |
24 | %mp_assert(
25 | iftrue=(%mfv_existfolder(&tgtfolder)=1),
26 | desc=Check if created folder exists
27 | )
28 |
29 | %mp_assertscope(SNAPSHOT)
30 | %mv_deleteviyafolder(path=&tgtfolder)
31 | /* ignore proc json vars */
32 | %mp_assertscope(COMPARE
33 | ,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADP2LEN MCLIB0_JADVLEN MCLIB2_JADP1LEN
34 | MCLIB2_JADVLEN
35 | )
36 |
37 | %mp_assert(
38 | iftrue=(%mfv_existfolder(&tgtfolder)=0),
39 | desc=Check if deleted folder is gone
40 | )
41 |
42 | /* delete folder with content */
43 | %mv_createfolder(path=&tgtfolder/content/and/stuff)
44 | %mp_assert(
45 | iftrue=(%mfv_existfolder(&tgtfolder/content/and/stuff)=1),
46 | desc=Check if folder with content exists
47 | )
48 | %mv_deleteviyafolder(path=&tgtfolder)
49 | %mp_assert(
50 | iftrue=(%mfv_existfolder(&tgtfolder)=0),
51 | desc=Check if deleted folder with subfolders is gone
52 | )
53 |
--------------------------------------------------------------------------------
/tests/viyaonly/mv_getfoldermembers.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mv_getfoldermembers macro
4 | @details Testing is performed by ensuring that the tests/macros folder
5 | contains more than 20 results (which also means the default was increased)
6 |
7 | SAS Macros
8 | @li mf_getapploc.sas
9 | @li mp_assertdsobs.sas
10 | @li mv_getfoldermembers.sas
11 |
12 | **/
13 | options mprint;
14 |
15 | %mv_getfoldermembers(
16 | root=%mf_getapploc()/tests/macros,
17 | outds=work.results
18 | )
19 |
20 | %mp_assertdsobs(work.results,
21 | desc=%str(Ensuring over 20 results found in %mf_getapploc()/tests/macros),
22 | test=ATLEAST 21,
23 | outds=work.test_results
24 | )
--------------------------------------------------------------------------------
/tests/viyaonly/mv_getjobcode.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mv_getjobcode macro
4 |
5 | SAS Macros
6 | @li mp_assert.sas
7 | @li mp_assertscope.sas
8 | @li mv_createjob.sas
9 | @li mv_getjobcode.sas
10 |
11 | **/
12 |
13 | /**
14 | * Test Case 1
15 | */
16 |
17 | /* write some code to a job */
18 | %let incode=%str(data test; set sashelp.class;run;);
19 | filename testref temp;
20 | data _null_;
21 | file testref;
22 | put "&incode";
23 | run;
24 | %mv_createjob(
25 | code=testref,
26 | path=&mcTestAppLoc/services/temp,
27 | name=some_job
28 | )
29 |
30 | /* now get the code back */
31 | %mp_assertscope(SNAPSHOT)
32 | %mv_getjobcode(
33 | path=&mcTestAppLoc/services/temp,
34 | name=some_job,
35 | outref=mycode
36 | )
37 | /* exclude automatic proc json macro variables from scope check */
38 | %mp_assertscope(COMPARE,
39 | ignorelist=MCLIB2_JADP1LEN MCLIB2_JADP2LEN MCLIB2_JADPNUM MCLIB2_JADVLEN
40 | MCLIB2_JADP3LEN
41 | )
42 |
43 | %let diditexist=NO;
44 | data work.test1;
45 | infile mycode;
46 | input;
47 | putlog _infile_;
48 | line=_infile_;
49 | check=symget('incode');
50 | if _infile_=symget('incode') then call symputx('diditexist','YES');
51 | run;
52 |
53 | %mp_assert(
54 | iftrue=(&diditexist=NO),
55 | desc=Check if the code that was sent was successfully retrieved
56 | )
57 |
--------------------------------------------------------------------------------
/tests/viyaonly/mv_getjobresult.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mv_createwebservice macro
4 |
5 | SAS Macros
6 | @li mp_assertdsobs.sas
7 | @li mv_createwebservice.sas
8 | @li mv_getjobresult.sas
9 | @li mv_jobflow.sas
10 |
11 | **/
12 |
13 | options mprint notes;
14 |
15 | /**
16 | * Test Case 1
17 | */
18 |
19 | /* create a service */
20 | filename testref temp;
21 | data _null_;
22 | file testref;
23 | put 'data test; set sashelp.class;run;';
24 | put '%webout(OPEN)';
25 | put '%webout(OBJ,test)';
26 | put '%webout(CLOSE)';
27 | run;
28 | %mv_createwebservice(
29 | path=&mcTestAppLoc/services/temp,
30 | code=testref,
31 | name=testsvc
32 | )
33 |
34 | /* trigger and wait for it to finish */
35 | data work.inputjobs;
36 | _program="&mcTestAppLoc/services/temp/testsvc";
37 | run;
38 | %mv_jobflow(inds=work.inputjobs
39 | ,maxconcurrency=4
40 | ,outds=work.results
41 | ,outref=myjoblog
42 | )
43 | /* stream the log */
44 | data _null_;
45 | infile myjoblog;
46 | input;
47 | put _infile_;
48 | run;
49 |
50 | /* fetch the uri */
51 | data _null_;
52 | set work.results;
53 | call symputx('uri',uri);
54 | put (_all_)(=);
55 | run;
56 |
57 | /* now get the results */
58 | %mv_getjobresult(uri=&uri
59 | ,result=WEBOUT_JSON
60 | ,outref=myweb
61 | ,outlib=myweblib
62 | )
63 | data _null_;
64 | infile myweb;
65 | input;
66 | putlog _infile_;
67 | run;
68 | data work.out;
69 | set myweblib.test;
70 | put (_all_)(=);
71 | run;
72 | %mp_assertdsobs(work.out,
73 | desc=Test1 - 19 obs from sashelp.class in service result,
74 | test=EQUALS 19,
75 | outds=work.test_results
76 | )
--------------------------------------------------------------------------------
/tests/viyaonly/mv_registerclient.test.1.sas:
--------------------------------------------------------------------------------
1 | /**
2 |
3 | @file
4 | @brief Testing mv_registerclient.sas macro
5 | @details Tests for successful registration. For this to work, the test
6 | account must be an admin.
7 |
8 | SAS Macros
9 | @li mf_getuniquename.sas
10 | @li mp_assertcolvals.sas
11 | @li mv_registerclient.sas
12 |
13 | **/
14 |
15 | /**
16 | * Test Case 1
17 | */
18 |
19 | %let id=%mf_getuniquename();
20 | %let sec=%mf_getuniquename();
21 | %mv_registerclient(client_id=&id,client_secret=&sec, outds=testds)
22 |
23 | data work.checkds;
24 | id="&id";
25 | sec="&sec";
26 | run;
27 | %mp_assertcolvals(work.testds.client_id,
28 | checkvals=work.checkds.id,
29 | desc=Checking client id was created
30 | test=ALLVALS
31 | )
32 | %mp_assertcolvals(work.testds.client_secret,
33 | checkvals=work.checkds.sec,
34 | desc=Checking client secret was created
35 | test=ALLVALS
36 | )
--------------------------------------------------------------------------------
/tests/viyaonly/mv_registerclient.test.2.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mv_registerclient.sas macro
4 | @details Tests for unsuccessful registration. To do this, overrides are
5 | applied for the mf_loc.sas and mp_abort.sas macros.
6 |
7 | SAS Macros
8 | @li mp_assert.sas
9 | @li mv_registerclient.sas
10 |
11 | **/
12 |
13 | /**
14 | * Test Case
15 | */
16 |
17 | %macro mf_loc(param);
18 | /does/not/exist
19 | %mend mf_loc;
20 |
21 | %macro mp_abort(iftrue=,mac=mp_abort.sas, type=, msg=);
22 | %if not(%eval(%unquote(&iftrue))) %then %return;
23 | %put %substr(&msg,1,16);
24 | %mp_assert(
25 | iftrue=("%substr(&msg,1,16)"="Unable to access"),
26 | desc=Check that abort happens when consul token is unavailable
27 | )
28 | %webout(OPEN)
29 | %webout(OBJ, TEST_RESULTS)
30 | %webout(CLOSE)
31 | %let syscc=0;
32 | data _null_;
33 | abort cancel nolist;
34 | run;
35 | %mend mp_abort;
36 |
37 | %mv_registerclient( outds=testds)
38 |
39 | %mp_assert(
40 | iftrue=(0=1),
41 | desc=Check that abort happens when consul token is unavailable
42 | )
--------------------------------------------------------------------------------
/tests/viyaonly/mv_webout.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mv_webout macro
4 |
5 | SAS Macros
6 | @li mf_getuniquefileref.sas
7 | @li mv_webout.sas
8 | @li mp_assert.sas
9 | @li mp_assertdsobs.sas
10 |
11 | **/
12 |
13 |
14 | /* testing FETCHing (WEB approach) */
15 |
16 | data _null_;
17 | call symputx('sasjs1data','area:$char4.'!!'0d0a'x!!'Adak');
18 | call symputx('sasjs_tables','areas');
19 | run;
20 | %put &=sasjs1data;
21 |
22 | %mv_webout(FETCH)
23 |
24 | %mp_assertdsobs(work.areas,
25 | desc=Test input table has 1 row,
26 | test=EQUALS 1,
27 | outds=work.test_results
28 | )
29 |
30 |
31 | %let fref=%mf_getuniquefileref();
32 | %global _metaperson;
33 | data some datasets;
34 | x=1;
35 | run;
36 | %mv_webout(OPEN,fref=&fref,stream=N)
37 | %mv_webout(ARR,some,fref=&fref,stream=N)
38 | %mv_webout(OBJ,datasets,fref=&fref,stream=N)
39 | %mv_webout(CLOSE,fref=&fref,stream=N)
40 |
41 | data _null_;
42 | infile &fref;
43 | input;
44 | putlog _infile_;
45 | run;
46 |
47 | libname test JSON (&fref);
48 | data root;
49 | set test.root;
50 | call symputx('checkval',sysvlong);
51 | run;
52 | data alldata;
53 | set test.alldata;
54 | run;
55 |
56 | %mp_assert(
57 | iftrue=(%str(&checkval)=%str(&sysvlong)),
58 | desc=Check if the sysvlong value was created
59 | )
60 |
--------------------------------------------------------------------------------
/tests/x-platform/mx_getcode.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mx_getcode.test.sas macro
4 |
5 | Be sure to run %let mcTestAppLoc=/Public/temp/macrocore;
when
6 | running in Studio
7 |
8 | SAS Macros
9 | @li mf_uid.sas
10 | @li mp_assert.sas
11 | @li mx_createwebservice.sas
12 | @li mx_getcode.sas
13 | @li mx_testservice.sas
14 |
15 | **/
16 |
17 | /* first create a service */
18 |
19 | %let item=%mf_uid();;
20 |
21 | %global test1;
22 | %let test1=FAIL;
23 |
24 | filename ft15f001 temp;
25 | parmcards4;
26 | %let test1=SUCCESS;
27 | ;;;;
28 | %mx_createwebservice(path=&mcTestAppLoc/temp,name=&item)
29 |
30 | %mx_getcode(&mcTestAppLoc/temp/&item,outref=testref1)
31 |
32 | %inc testref1/lrecl=1000;
33 |
34 | %mp_assert(
35 | iftrue=(&test1=SUCCESS),
36 | desc=code was successfully fetched,
37 | outds=work.test_results
38 | )
39 |
--------------------------------------------------------------------------------
/tests/x-platform/mx_getgroups.test.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Testing mx_getgroups.test.sas macro
4 |
5 | Be sure to run %let mcTestAppLoc=/Public/temp/macrocore;
when
6 | running in Studio
7 |
8 | SAS Macros
9 | @li mf_nobs.sas
10 | @li mf_getuser.sas
11 | @li mp_assert.sas
12 | @li mx_getgroups.sas
13 |
14 | **/
15 |
16 |
17 | %mx_getgroups(outds=work.test1)
18 |
19 | %mp_assert(
20 | iftrue=(%mf_nobs(work.test1)>0),
21 | desc=groups were found,
22 | outds=work.test_results
23 | )
24 | %mp_assertcols(work.test1,
25 | cols=groupuri groupname groupdesc,
26 | test=ALL,
27 | desc=check all columns exist
28 | )
29 |
30 | %mx_getgroups(outds=work.test2,user=%mf_getuser())
31 |
32 | %mp_assert(
33 | iftrue=(%mf_nobs(work.test2)>0),
34 | desc=groups for current user were found,
35 | outds=work.test_results
36 | )
37 | %mp_assertcols(work.test2,
38 | cols=groupuri groupname groupdesc,
39 | test=ALL,
40 | desc=check all columns exist
41 | )
--------------------------------------------------------------------------------
/viya/mfv_existfile.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Checks whether a file exists in SAS Drive
4 | @details Returns 1 if the file exists, and 0 if it doesn't. Works by
5 | attempting to assign a fileref with the filesrvc engine. If not found, the
6 | syscc is automatically set to a non zero value - so in this case it is reset.
7 | To avoid hiding issues, there is therefore a test at the start to ensure the
8 | syscc is zero.
9 |
10 | Usage:
11 |
12 | %put %mfv_existfile(/does/exist.txt);
13 | %put %mfv_existfile(/does/not/exist.txt);
14 |
15 | @param [in] filepath The full path to the file on SAS drive
16 | (eg /Public/myfile.txt)
17 |
18 | SAS Macros
19 | @li mf_abort.sas
20 | @li mf_getuniquefileref.sas
21 |
22 | Related Macros
23 | @li mfv_existfolder.sas
24 |
25 | @version 3.5
26 | @author [Allan Bowe](https://www.linkedin.com/in/allanbowe/)
27 | **/
28 |
29 | %macro mfv_existfile(filepath
30 | )/*/STORE SOURCE*/;
31 |
32 | %mf_abort(
33 | iftrue=(&syscc ne 0),
34 | msg=Cannot enter mfv_existfile.sas with syscc=&syscc
35 | )
36 |
37 | %local fref rc path name;
38 | %let fref=%mf_getuniquefileref();
39 | %let name=%scan(&filepath,-1,/);
40 | %let path=%substr(&filepath,1,%length(&filepath)-%length(&name)-1);
41 |
42 | %if %sysfunc(filename(fref,,filesrvc,folderPath="&path" filename="&name"))=0
43 | %then %do;
44 | %sysfunc(fexist(&fref))
45 | %let rc=%sysfunc(filename(fref));
46 | %end;
47 | %else %do;
48 | 0
49 | %let syscc=0;
50 | %end;
51 |
52 | %mend mfv_existfile;
--------------------------------------------------------------------------------
/viya/mfv_existfolder.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Checks whether a folder exists in SAS Drive
4 | @details Returns 1 if the folder exists, and 0 if it doesn't. Works by
5 | attempting to assign a fileref with the filesrvc engine. If not found, the
6 | syscc is automatically set to a non zero value - so in this case it is reset.
7 | To avoid hiding issues, there is therefore a test at the start to ensure the
8 | syscc is zero.
9 |
10 | Usage:
11 |
12 | %put %mfv_existfolder(/does/exist);
13 | %put %mfv_existfolder(/does/not/exist);
14 |
15 | @param [in] path The path to the folder on SAS drive
16 |
17 | SAS Macros
18 | @li mf_abort.sas
19 | @li mf_getuniquefileref.sas
20 |
21 | Related Macros
22 | @li mfv_existfile.sas
23 |
24 | @version 3.5
25 | @author [Allan Bowe](https://www.linkedin.com/in/allanbowe/)
26 | **/
27 |
28 | %macro mfv_existfolder(path
29 | )/*/STORE SOURCE*/;
30 |
31 | %mf_abort(
32 | iftrue=(&syscc ne 0),
33 | msg=Cannot enter mfv_existfolder.sas with syscc=&syscc
34 | )
35 |
36 | %local fref rc;
37 | %let fref=%mf_getuniquefileref();
38 |
39 | %if %sysfunc(filename(fref,,filesrvc,folderPath="&path"))=0 %then %do;
40 | 1
41 | %let rc=%sysfunc(filename(fref));
42 | %end;
43 | %else %do;
44 | 0
45 | %let syscc=0;
46 | %end;
47 |
48 | %mend mfv_existfolder;
--------------------------------------------------------------------------------
/viya/mfv_getfolderpath.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Returns the path of a folder from the URI
4 | @details Makes use of the SYSMSG() ER8OR response, which resolves the uri,
5 | seemingly without entering an er8or state.
6 |
7 | Usage:
8 |
9 | %mv_createfolder(path=/public/demo)
10 | %let uri=%mfv_getpathuri(/public/demo);
11 | %put %mfv_getfolderpath(&uri);
12 |
13 | Notice above the new path has an uppercase P - the correct path.
14 |
15 | @param [in] uri The uri of the folder -eg /folders/folders/xxxx)
16 |
17 | SAS Macros
18 | @li mf_getuniquefileref.sas
19 |
20 | Related Macros
21 | @li mfv_getpathuri.sas
22 |
23 | @version 4
24 | @author [Allan Bowe](https://www.linkedin.com/in/allanbowe/)
25 | **/
26 | %macro mfv_getfolderpath(uri
27 | )/*/STORE SOURCE*/;
28 |
29 | %local fref rc path msg var /* var used to avoid delete timing issue */;
30 | %let fref=%mf_getuniquefileref();
31 | %if %quote(%substr(%str(&uri),1,17)) ne %quote(/folders/folders/)
32 | %then %do;
33 | %put &sysmacroname: Invalid URI: &uri;
34 | %end;
35 | %else %if %sysfunc(filename(fref,,filesrvc,folderuri="&uri" ))=0
36 | %then %do;
37 | %let var=_FILESRVC_&fref._URI;
38 | %local fid ;
39 | %let fid= %sysfunc(fopen(&fref,I));
40 | %let msg=%quote(%sysfunc(sysmsg()));
41 |
42 | %unquote(%scan(&msg,2,%str(,.)))
43 |
44 | %let rc=%sysfunc(fclose(&fid));
45 | %let rc=%sysfunc(filename(fref));
46 | %symdel &var;
47 | %end;
48 | %else %do;
49 | %put &sysmacroname: Not Found: &uri;
50 | %let syscc=0;
51 | %end;
52 |
53 | %mend mfv_getfolderpath ;
--------------------------------------------------------------------------------
/viya/mfv_getpathuri.sas:
--------------------------------------------------------------------------------
1 | /**
2 | @file
3 | @brief Returns the uri of a file or folder
4 | @details The automatic variable `_FILESRVC_[fref]_URI` is used after assigning
5 | a fileref using the filesrvc engine.
6 |
7 | Usage:
8 |
9 | %put %mfv_getpathuri(/Public/folder/file.txt);
10 | %put %mfv_getpathuri(/Public/folder);
11 |
12 | @param [in] filepath The full path to the file on SAS drive
13 | (eg /Public/myfile.txt)
14 |
15 | SAS Macros
16 | @li mf_abort.sas
17 | @li mf_getuniquefileref.sas
18 |
19 | Related Macros
20 | @li mfv_existfile.sas
21 | @li mfv_existfolder.sas
22 |
23 | @version 3.5
24 | @author [Allan Bowe](https://www.linkedin.com/in/allanbowe/)
25 | **/
26 |
27 | %macro mfv_getpathuri(filepath
28 | )/*/STORE SOURCE*/;
29 |
30 | %mf_abort(
31 | iftrue=(&syscc ne 0),
32 | msg=Cannot enter &sysmacroname with syscc=&syscc
33 | )
34 |
35 | %local fref rc path name var /* var is used to avoid delete timing issue */;
36 | %let fref=%mf_getuniquefileref();
37 | %let name=%scan(&filepath,-1,/);
38 | %let path=%substr(&filepath,1,%length(&filepath)-%length(&name)-1);
39 |
40 | %if %sysfunc(filename(fref,,filesrvc,folderPath="&path" filename="&name"))=0
41 | %then %do;
42 | %let var=_FILESRVC_&fref._URI;
43 | %str(&&&var)
44 | %let rc=%sysfunc(filename(fref));
45 | %symdel &var;
46 | %end;
47 | %else %do;
48 | %put &sysmacroname: did not find &filepath;
49 | %let syscc=0;
50 | %end;
51 |
52 | %mend mfv_getpathuri;
--------------------------------------------------------------------------------