From b1a29f0775f443c7b6dabb06fd212993d9b4a590 Mon Sep 17 00:00:00 2001 From: Luke Rodgers Date: Sat, 4 Feb 2023 16:37:05 -0500 Subject: [PATCH] Add some basic specs Nothing revolutionary, just getting the spec ball rolling, mostly. --- spec/fixtures/dynamic_definition.rb | 5 + spec/fixtures/empty_def_file.rb | 1 + spec/fixtures/inapplicable_def_file.rb | 5 + spec/fixtures/sample_dump.sql | 176 +++++++++++++++++++++++++ spec/fixtures/static_def.rb | 5 + spec/pg_dump_anonymize_spec.rb | 59 ++++++++- spec/spec_helper.rb | 2 + 7 files changed, 251 insertions(+), 2 deletions(-) create mode 100644 spec/fixtures/dynamic_definition.rb create mode 100644 spec/fixtures/empty_def_file.rb create mode 100644 spec/fixtures/inapplicable_def_file.rb create mode 100644 spec/fixtures/sample_dump.sql create mode 100644 spec/fixtures/static_def.rb diff --git a/spec/fixtures/dynamic_definition.rb b/spec/fixtures/dynamic_definition.rb new file mode 100644 index 0000000..6be4b84 --- /dev/null +++ b/spec/fixtures/dynamic_definition.rb @@ -0,0 +1,5 @@ +{ + users: { + name: -> { "Jimbo #{SecureRandom.hex(8)}" } + } +} diff --git a/spec/fixtures/empty_def_file.rb b/spec/fixtures/empty_def_file.rb new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/spec/fixtures/empty_def_file.rb @@ -0,0 +1 @@ +{} diff --git a/spec/fixtures/inapplicable_def_file.rb b/spec/fixtures/inapplicable_def_file.rb new file mode 100644 index 0000000..9ea219c --- /dev/null +++ b/spec/fixtures/inapplicable_def_file.rb @@ -0,0 +1,5 @@ +{ + foo: { + bar: "baz" + } +} diff --git a/spec/fixtures/sample_dump.sql b/spec/fixtures/sample_dump.sql new file mode 100644 index 0000000..f924749 --- /dev/null +++ b/spec/fixtures/sample_dump.sql @@ -0,0 +1,176 @@ +-- +-- PostgreSQL database dump +-- + +-- Dumped from database version 11.18 +-- Dumped by pg_dump version 14.6 (Homebrew) + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +SET default_tablespace = ''; + +-- +-- Name: organizations; Type: TABLE; Schema: public; Owner: luke +-- + +CREATE TABLE public.organizations ( + id integer NOT NULL, + name character varying NOT NULL, + created_at timestamp without time zone +); + + +ALTER TABLE public.organizations OWNER TO luke; + +-- +-- Name: organizations_id_seq; Type: SEQUENCE; Schema: public; Owner: luke +-- + +CREATE SEQUENCE public.organizations_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER TABLE public.organizations_id_seq OWNER TO luke; + +-- +-- Name: organizations_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: luke +-- + +ALTER SEQUENCE public.organizations_id_seq OWNED BY public.organizations.id; + + +-- +-- Name: users; Type: TABLE; Schema: public; Owner: luke +-- + +CREATE TABLE public.users ( + id integer NOT NULL, + name character varying NOT NULL, + org_id smallint NOT NULL, + created_at timestamp without time zone, + birthdate date +); + + +ALTER TABLE public.users OWNER TO luke; + +-- +-- Name: users_id_seq; Type: SEQUENCE; Schema: public; Owner: luke +-- + +CREATE SEQUENCE public.users_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER TABLE public.users_id_seq OWNER TO luke; + +-- +-- Name: users_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: luke +-- + +ALTER SEQUENCE public.users_id_seq OWNED BY public.users.id; + + +-- +-- Name: organizations id; Type: DEFAULT; Schema: public; Owner: luke +-- + +ALTER TABLE ONLY public.organizations ALTER COLUMN id SET DEFAULT nextval('public.organizations_id_seq'::regclass); + + +-- +-- Name: users id; Type: DEFAULT; Schema: public; Owner: luke +-- + +ALTER TABLE ONLY public.users ALTER COLUMN id SET DEFAULT nextval('public.users_id_seq'::regclass); + + +-- +-- Data for Name: organizations; Type: TABLE DATA; Schema: public; Owner: luke +-- + +COPY public.organizations (id, name, created_at) FROM stdin; +1 Test org 2023-02-04 16:27:51.797666 +2 Test org 2 2023-02-04 16:27:55.293966 +\. + + +-- +-- Data for Name: users; Type: TABLE DATA; Schema: public; Owner: luke +-- + +COPY public.users (id, name, org_id, created_at, birthdate) FROM stdin; +1 test user 1 1 2023-02-04 16:28:34.391467 1990-01-01 +2 test user 2 1 2023-02-04 16:28:44.292242 1989-01-01 +3 test user 3 2 2023-02-04 16:28:52.430384 1988-01-01 +\. + + +-- +-- Name: organizations_id_seq; Type: SEQUENCE SET; Schema: public; Owner: luke +-- + +SELECT pg_catalog.setval('public.organizations_id_seq', 2, true); + + +-- +-- Name: users_id_seq; Type: SEQUENCE SET; Schema: public; Owner: luke +-- + +SELECT pg_catalog.setval('public.users_id_seq', 3, true); + + +-- +-- Name: organizations organizations_pkey; Type: CONSTRAINT; Schema: public; Owner: luke +-- + +ALTER TABLE ONLY public.organizations + ADD CONSTRAINT organizations_pkey PRIMARY KEY (id); + + +-- +-- Name: users users_pkey; Type: CONSTRAINT; Schema: public; Owner: luke +-- + +ALTER TABLE ONLY public.users + ADD CONSTRAINT users_pkey PRIMARY KEY (id); + + +-- +-- Name: users_org_idx; Type: INDEX; Schema: public; Owner: luke +-- + +CREATE INDEX users_org_idx ON public.users USING btree (org_id); + + +-- +-- Name: users fk_users_organizations; Type: FK CONSTRAINT; Schema: public; Owner: luke +-- + +ALTER TABLE ONLY public.users + ADD CONSTRAINT fk_users_organizations FOREIGN KEY (org_id) REFERENCES public.organizations(id); + + +-- +-- PostgreSQL database dump complete +-- + diff --git a/spec/fixtures/static_def.rb b/spec/fixtures/static_def.rb new file mode 100644 index 0000000..81ff818 --- /dev/null +++ b/spec/fixtures/static_def.rb @@ -0,0 +1,5 @@ +{ + users: { + name: "Jimbo" + } +} diff --git a/spec/pg_dump_anonymize_spec.rb b/spec/pg_dump_anonymize_spec.rb index 4c0dded..fa79eb6 100644 --- a/spec/pg_dump_anonymize_spec.rb +++ b/spec/pg_dump_anonymize_spec.rb @@ -3,7 +3,62 @@ expect(PgDumpAnonymize::VERSION).not_to be nil end - it "does something useful" do - expect(false).to eq(true) + it "can process a file with no transformations, producing an exact copy" do + def_file = "spec/fixtures/empty_def_file.rb" + dump_file = File.open("spec/fixtures/sample_dump.sql") + out_file = Tempfile.new('foo') + + PgDumpAnonymize.anonymize(def_file, dump_file, out_file) + + dump_file.rewind + out_file.rewind + expect(dump_file.read).to eql(out_file.read) + end + + it "can process a file with a static transformation" do + def_file = "spec/fixtures/static_def.rb" + dump_file = File.open("spec/fixtures/sample_dump.sql") + out_file = Tempfile.new('foo') + + PgDumpAnonymize.anonymize(def_file, dump_file, out_file) + + out_file.rewind + expect(out_file.grep(/test user/i)).to eql([]) + out_file.rewind + expect(out_file.grep(/Jimbo/i).size).to eql(3) + end + + it "can process a file with a dynamic transformation" do + def_file = "spec/fixtures/dynamic_definition.rb" + dump_file = File.open("spec/fixtures/sample_dump.sql") + out_file = Tempfile.new('foo') + + PgDumpAnonymize.anonymize(def_file, dump_file, out_file) + + out_file.rewind + expect(out_file.grep(/test user/i)).to eql([]) + out_file.rewind + matches = out_file.grep(/Jimbo/i) + line1, line2, line3 = matches + + jimboA, jimboB, jimboC = matches.map do |line| + values = line.split("\t") + values[1] + end + expect(jimboA).not_to eql(jimboB) + expect(jimboA).not_to eql(jimboC) + expect(jimboB).not_to eql(jimboC) + end + + it "treats def file table references to absent tables as a noop" do + def_file = "spec/fixtures/inapplicable_def_file.rb" + dump_file = File.open("spec/fixtures/sample_dump.sql") + out_file = Tempfile.new('foo') + + PgDumpAnonymize.anonymize(def_file, dump_file, out_file) + + dump_file.rewind + out_file.rewind + expect(dump_file.read).to eql(out_file.read) end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index d5902cf..7dd4547 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,5 +1,7 @@ require "bundler/setup" require "pg_dump_anonymize" +require "tempfile" +require "securerandom" RSpec.configure do |config| # Enable flags like --only-failures and --next-failure