This commit is contained in:
2023-07-13 10:33:43 -04:00
commit 9195787f8b
16 changed files with 427 additions and 0 deletions

3
static-analysis/.envrc Normal file
View File

@@ -0,0 +1,3 @@
source_url "https://raw.githubusercontent.com/cachix/devenv/d1f7b48e35e6dee421cfd0f51481d17f77586997/direnvrc" "sha256-YBzqskFZxmNb3kYVoKD9ZixoPXJh1C9ZvTLGFRkauZ0="
use devenv

5
static-analysis/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
# Devenv
.devenv*
devenv.local.nix

View File

@@ -0,0 +1,4 @@
x = 1
y = 2
z = x + y
puts z

View File

@@ -0,0 +1 @@
x = 5 + "rocks"

View File

@@ -0,0 +1,6 @@
x = 1
begin
x = 3
end
->(x) { x + 1 }
puts x

View File

@@ -0,0 +1,9 @@
params.permit([1, 2, 3])
params2
.permit(["a", "b", "c"])
params3
.
permit(["x", "y", "z"])

5
static-analysis/Gemfile Normal file
View File

@@ -0,0 +1,5 @@
# frozen_string_literal: true
source 'https://rubygems.org'
gem 'rubocop', path: '/home/adammo/repos/presentations/static-analysis/rubocop'

View File

@@ -0,0 +1,42 @@
PATH
remote: rubocop
specs:
rubocop (1.54.1)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.2.2.3)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.28.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
GEM
remote: https://rubygems.org/
specs:
ast (2.4.2)
json (2.6.3)
language_server-protocol (3.17.0.3)
parallel (1.23.0)
parser (3.2.2.3)
ast (~> 2.4.1)
racc
racc (1.7.1)
rainbow (3.1.1)
regexp_parser (2.8.1)
rexml (3.2.5)
rubocop-ast (1.29.0)
parser (>= 3.2.1.0)
ruby-progressbar (1.13.0)
unicode-display_width (2.4.2)
PLATFORMS
x86_64-linux
DEPENDENCIES
rubocop!
BUNDLED WITH
2.2.33

101
static-analysis/README.org Normal file
View File

@@ -0,0 +1,101 @@
#+TITLE: Program Analysis
#+Author: Adam Mohammed
* Program Analysis tools
Generally program analysis tools come in two forms, static and
dynamic. Each has tradeoffs that we need to understand, especially
when we start to build these tools.
It's important to understand what each analysis tool is good for,
knowing what it's strong at detecting, as well as knowing what they
are not good for and where they struggle.
** Examples of Static Analysis
RuboCop
Gofmt
Rufo
*** Good
- Detecting syntax errors
- Detecting simple semantic errors
- Detecting style violations
- Detecting code convention violations
*** Bad
- Prone to false positives and false negatives
- Requires access to source code, including libraries
- Does not account for runtime environment
** Examples of Dynamic Analysis
Profilers
- ruby-prof
Memory leak detection
- Valgrind
Data Races
- Go race detector
*** Good
- Detect bugs that only can occur at runtime
- Capable of measuring things inlfuenced by factors outside of source code
- e.g. Network latency, External errors, etc
- Generally less false positives and false negatives because error
cases must occur to be detected
*** Bad
- Requires actually violating edge cases to report them
- Often incurs performance penalty to instrument live code
- True positives can be missed for code paths that are not exercised often.
** Problem we're actually facing
- Monolith is large and old
- OAS is used as the source of truth to generate clients and documentation that customers rely on
- Monolith and OAS don't agree most of the time
** Solutions we're trying
https://github.com/equinixmetal/api-spec-inspector - form of SA
** Back to basics
How do programming languages do their job?
Source code -> interpreted -> output
If you're in a compiled languages
source code -> compiled -> executable -> output
We treat "interpreters" and "compilers" as black boxes for the most part.
Let's pull back the curtains on these things though:
** How does code get interpreted?
1. Show ruby-parse
2. Talk about AST
** Utilizing the AST
ex 01-03_
** Problem areas for test parsing
ex 04 vrf params
** Rubocop Examples
https://github.com/rubocop/rubocop/blob/02c32b4cf3801f9cf4cca4b3f1f4288aaee2ad5c/lib/rubocop/cop/lint/useless_setter_call.rb

View File

@@ -0,0 +1,57 @@
def create
@interconnection = if create_with_service_tokens?
::Network::Interconnection::Connection::CreateWithServiceTokens.call(create_with_service_tokens_params)
else
::Network::Interconnection::Connection::Create.call(create_params)
end
if @interconnection.valid?
render "interconnections/connections/show", status: :created, location: interconnection_path(@interconnection.id)
else
render_validation_errors(@interconnection)
end
end
def create_params
# TODO: Remove facility from create params after making metro required in swagger docs
@facility = Facility.find_by_id_or(:code, params[:facility_id]) if params[:facility_id]
params.required([:name, :redundancy, :type])
params[:contact_email] = current_user.email unless params.has_key?(:contact_email)
params[:speed] = ::Network::Interconnection::InterconnectionPort.parse_speed(params[:speed]) if params.has_key?(:speed)
permitted = [:contact_email, :description, :name, :redundancy, :speed, :facility_id, :metro_id, :metro, :type, tags: []]
permitted << { vlans: [] } if advanced_shared_create_enabled?
permitted << :mode if dedicated_interconnection_mode_enabled? && params[:type] == "dedicated"
params
.permit(*permitted)
.merge(
facility: @facility,
metro: @metro,
project: @project,
organization: @organization,
virtual_networks: @virtual_networks,
)
end
def create_with_service_tokens_params
set_service_token_params
# TODO: Remove VRF feature flag check after VRF is released.
array_params = { tags: [], vlans: [] }
array_params = array_params.merge(vrfs: []) if Feature.enabled?(Feature::VRF_ON_SHARED_CONNECTIONS, @organization)
permitted = [:description, :locked, :name, :redundancy, :speed, :contact_email, :metro_id, :type, :service_token_type, array_params]
normalize_params
params
.permit(*permitted)
.merge(
vrfs: @vrfs,
metro: @metro,
project: @project,
organization: @organization,
virtual_networks: @virtual_networks,
)
end

156
static-analysis/devenv.lock Normal file
View File

@@ -0,0 +1,156 @@
{
"nodes": {
"devenv": {
"locked": {
"dir": "src/modules",
"lastModified": 1689195827,
"narHash": "sha256-0+vH0tLjScnR6mpywjIOqS9BGbBUWY8IcWXuo/j6+l8=",
"owner": "cachix",
"repo": "devenv",
"rev": "7d5b629ec05db9b954a1cfc34a0fafec420e7377",
"type": "github"
},
"original": {
"dir": "src/modules",
"owner": "cachix",
"repo": "devenv",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1685518550,
"narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"pre-commit-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1660459072,
"narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1689168768,
"narHash": "sha256-mCw3LPg2jJkapvJpkd1IZ8k0IJlSG2ECvz3vcOAu+Uo=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6fd9edc94426a3c050ad589c8f033b5ca55454c7",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1685801374,
"narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c37ca420157f4abc31e26f436c1145f8951ff373",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-23.05",
"repo": "nixpkgs",
"type": "github"
}
},
"pre-commit-hooks": {
"inputs": {
"flake-compat": "flake-compat",
"flake-utils": "flake-utils",
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1688596063,
"narHash": "sha256-9t7RxBiKWHygsqXtiNATTJt4lim/oSYZV3RG8OjDDng=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "c8d18ba345730019c3faf412c96a045ade171895",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"root": {
"inputs": {
"devenv": "devenv",
"nixpkgs": "nixpkgs",
"pre-commit-hooks": "pre-commit-hooks"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View File

@@ -0,0 +1,29 @@
{ pkgs, ... }:
{
# https://devenv.sh/packages/
packages = [
pkgs.ruby_3_0
pkgs.rubyPackages_3_0.rubocop
];
# https://devenv.sh/scripts/
scripts.hello.exec = "echo hello from $GREET";
enterShell = ''
hello
git --version
'';
# https://devenv.sh/languages/
# languages.nix.enable = true;
# https://devenv.sh/pre-commit-hooks/
# pre-commit.hooks.shellcheck.enable = true;
# https://devenv.sh/processes/
# processes.ping.exec = "ping example.com";
# See full reference at https://devenv.sh/reference/options/
}

View File

@@ -0,0 +1,3 @@
inputs:
nixpkgs:
url: github:NixOS/nixpkgs/nixpkgs-unstable

View File

@@ -0,0 +1,2 @@
k = {a: 1, b: 2, a: 3}
puts k

Submodule static-analysis/rubocop added at 02c32b4cf3

3
static-analysis/test1.rb Normal file
View File

@@ -0,0 +1,3 @@
x = 1
y = 2
x + y